]> git.saurik.com Git - wxWidgets.git/commitdiff
Ryan's cumulative wxActiveX and media control patch (1427775)
authorVadim Zeitlin <vadim@wxwidgets.org>
Fri, 10 Feb 2006 19:37:40 +0000 (19:37 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Fri, 10 Feb 2006 19:37:40 +0000 (19:37 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37461 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

19 files changed:
build/bakefiles/build_cfg.bkl
build/bakefiles/config.bkl
build/bakefiles/files.bkl
build/bakefiles/multilib.bkl
configure.in
docs/latex/wx/activexcontainer.tex [new file with mode: 0644]
docs/latex/wx/activexevt.tex [new file with mode: 0644]
docs/latex/wx/classes.tex
docs/latex/wx/mediactrl.tex
docs/latex/wx/mediaevt.tex
include/wx/mediactrl.h
include/wx/msw/ole/activex.h
samples/mediaplayer/mediaplayer.cpp
src/common/mediactrlcmn.cpp
src/mac/carbon/mediactrl.cpp
src/msw/mediactrl_am.cpp [new file with mode: 0644]
src/msw/mediactrl_wmp10.cpp [new file with mode: 0644]
src/msw/ole/activex.cpp
src/unix/mediactrl.cpp

index cea46c0497771d29dc1b8eaf9f2fc85079c3b99f..99e6292ca0a1e1b828d96f2747db43faefd1b8c5 100644 (file)
@@ -39,6 +39,7 @@
                 @echo USE_THREADS=$(USE_THREADS) >>$(BUILD_CFG_FILE)
                 @echo USE_GUI=$(USE_GUI) >>$(BUILD_CFG_FILE)
                 @echo USE_HTML=$(USE_HTML) >>$(BUILD_CFG_FILE)
                 @echo USE_THREADS=$(USE_THREADS) >>$(BUILD_CFG_FILE)
                 @echo USE_GUI=$(USE_GUI) >>$(BUILD_CFG_FILE)
                 @echo USE_HTML=$(USE_HTML) >>$(BUILD_CFG_FILE)
+                @echo USE_MEDIA=$(USE_MEDIA) >>$(BUILD_CFG_FILE)
                 @echo USE_ODBC=$(USE_ODBC) >>$(BUILD_CFG_FILE)
                 @echo USE_OPENGL=$(USE_OPENGL) >>$(BUILD_CFG_FILE)
                 @echo USE_QA=$(USE_QA) >>$(BUILD_CFG_FILE)
                 @echo USE_ODBC=$(USE_ODBC) >>$(BUILD_CFG_FILE)
                 @echo USE_OPENGL=$(USE_OPENGL) >>$(BUILD_CFG_FILE)
                 @echo USE_QA=$(USE_QA) >>$(BUILD_CFG_FILE)
index f6a4ea05181f2da07dd5bab5330f8c27fe558449..2172cc697e6feef84e6bdd45c48f4e95221d5a7b 100644 (file)
@@ -180,6 +180,14 @@ Acts according to BUILD by default.
         </description>
     </option>
 
         </description>
     </option>
 
+    <option name="USE_MEDIA">
+        <values>0,1</values>
+        <default-value>1</default-value>
+        <description>
+            Build multimedia library (USE_GUI must be 1)?
+        </description>
+    </option>
+
     <option name="USE_XRC">
         <values>0,1</values>
         <default-value>1</default-value>
     <option name="USE_XRC">
         <values>0,1</values>
         <default-value>1</default-value>
@@ -403,6 +411,7 @@ Set the version of your Mingw installation here.
         <set var="RUNTIME_LIBS">dynamic</set>
         <set var="OFFICIAL_BUILD">0</set>
         <set var="USE_HTML">1</set>
         <set var="RUNTIME_LIBS">dynamic</set>
         <set var="OFFICIAL_BUILD">0</set>
         <set var="USE_HTML">1</set>
+         <set var="USE_MEDIA">1</set>
         <set var="USE_XRC">1</set>
         <set var="USE_OPENGL">1</set>
         <set var="USE_ODBC">1</set>
         <set var="USE_XRC">1</set>
         <set var="USE_OPENGL">1</set>
         <set var="USE_ODBC">1</set>
index 35b83b9c2803357f7e8300f3eb57730dd60fbdb4..58b45a13e630d1c76bca2f5254cd591c0328158c 100644 (file)
@@ -2657,7 +2657,8 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file!
 </set>
 
 <set var="MEDIA_MSW_SRC" hints="files">
 </set>
 
 <set var="MEDIA_MSW_SRC" hints="files">
-    src/msw/mediactrl.cpp
+    src/msw/mediactrl_am.cpp
+    src/msw/mediactrl_wmp10.cpp
     src/msw/ole/activex.cpp
 </set>
 <set var="MEDIA_MSW_HDR" hints="files">
     src/msw/ole/activex.cpp
 </set>
 <set var="MEDIA_MSW_HDR" hints="files">
index d0c4ff1c5a48c968914d942590825d110eb9d084..f2cef3f4243507d8776e88a6df550d6f433fd933 100644 (file)
     <!-- ================================================================= -->
 
     <dll id="mediadll" template="wx_dll"
     <!-- ================================================================= -->
 
     <dll id="mediadll" template="wx_dll"
-         cond="SHARED=='1' and USE_GUI=='1' and MONOLITHIC=='0'">
+         cond="SHARED=='1' and USE_MEDIA=='1' and USE_GUI=='1' and MONOLITHIC=='0'">
         <define>WXUSINGDLL</define>
         <define>WXMAKINGDLL_MEDIA</define>
         <sources>$(MEDIA_SRC)</sources>
         <define>WXUSINGDLL</define>
         <define>WXMAKINGDLL_MEDIA</define>
         <sources>$(MEDIA_SRC)</sources>
     </dll>
 
     <lib id="medialib" template="wx_lib"
     </dll>
 
     <lib id="medialib" template="wx_lib"
-         cond="SHARED=='0' and USE_GUI=='1' and MONOLITHIC=='0'">
+         cond="SHARED=='0' and USE_MEDIA=='1' and USE_GUI=='1' and MONOLITHIC=='0'">
         <sources>$(MEDIA_SRC)</sources>
         <msvc-headers>$(MEDIA_HDR)</msvc-headers>
     </lib>
         <sources>$(MEDIA_SRC)</sources>
         <msvc-headers>$(MEDIA_HDR)</msvc-headers>
     </lib>
index 8e0fb2787a17a7980c47850fe5b665700294ac5b..34f53337e82c8fd94c1f0226bdfdf996bb1bb516 100644 (file)
@@ -422,6 +422,7 @@ if test $DEBUG_CONFIGURE = 1; then
   DEFAULT_wxUSE_TEXTFILE=no
   DEFAULT_wxUSE_SOUND=no
   DEFAULT_wxUSE_MEDIACTRL=no
   DEFAULT_wxUSE_TEXTFILE=no
   DEFAULT_wxUSE_SOUND=no
   DEFAULT_wxUSE_MEDIACTRL=no
+  DEFAULT_wxUSE_GSTREAMER8=no
   DEFAULT_wxUSE_INTL=no
   DEFAULT_wxUSE_CONFIG=no
   DEFAULT_wxUSE_FONTMAP=no
   DEFAULT_wxUSE_INTL=no
   DEFAULT_wxUSE_CONFIG=no
   DEFAULT_wxUSE_FONTMAP=no
@@ -624,6 +625,7 @@ else
   DEFAULT_wxUSE_TEXTFILE=yes
   DEFAULT_wxUSE_SOUND=yes
   DEFAULT_wxUSE_MEDIACTRL=no
   DEFAULT_wxUSE_TEXTFILE=yes
   DEFAULT_wxUSE_SOUND=yes
   DEFAULT_wxUSE_MEDIACTRL=no
+  DEFAULT_wxUSE_GSTREAMER8=no
   DEFAULT_wxUSE_INTL=yes
   DEFAULT_wxUSE_CONFIG=yes
   DEFAULT_wxUSE_FONTMAP=yes
   DEFAULT_wxUSE_INTL=yes
   DEFAULT_wxUSE_CONFIG=yes
   DEFAULT_wxUSE_FONTMAP=yes
@@ -935,6 +937,7 @@ WX_ARG_ENABLE(timer,         [  --enable-timer          use wxTimer class], wxUS
 WX_ARG_ENABLE(unicode,       [  --enable-unicode        compile wxString with Unicode support], wxUSE_UNICODE)
 WX_ARG_ENABLE(sound,         [  --enable-sound          use wxSound class], wxUSE_SOUND)
 WX_ARG_ENABLE(mediactrl,     [  --enable-mediactrl      use wxMediaCtrl class], wxUSE_MEDIACTRL)
 WX_ARG_ENABLE(unicode,       [  --enable-unicode        compile wxString with Unicode support], wxUSE_UNICODE)
 WX_ARG_ENABLE(sound,         [  --enable-sound          use wxSound class], wxUSE_SOUND)
 WX_ARG_ENABLE(mediactrl,     [  --enable-mediactrl      use wxMediaCtrl class], wxUSE_MEDIACTRL)
+WX_ARG_ENABLE(gstreamer8,     [  --enable-gstreamer8      force GStreamer 0.8 instead of 0.10 with the wxMediaCtrl class on unix], wxUSE_GSTREAMER8)
 WX_ARG_ENABLE(wxprintfv,     [  --enable-wxprintfv      use wxWidgets implementation of vprintf()], wxUSE_EXPERIMENTAL_PRINTF)
 WX_ARG_ENABLE(zipstream,     [  --enable-zipstream      use wxZip streams], wxUSE_ZIPSTREAM)
 
 WX_ARG_ENABLE(wxprintfv,     [  --enable-wxprintfv      use wxWidgets implementation of vprintf()], wxUSE_EXPERIMENTAL_PRINTF)
 WX_ARG_ENABLE(zipstream,     [  --enable-zipstream      use wxZip streams], wxUSE_ZIPSTREAM)
 
@@ -6754,6 +6757,8 @@ dnl ---------------------------------------------------------------------------
 dnl wxMediaCtrl
 dnl ---------------------------------------------------------------------------
 
 dnl wxMediaCtrl
 dnl ---------------------------------------------------------------------------
 
+USE_MEDIA=0
+
 if test "$wxUSE_MEDIACTRL" = "yes"; then
     dnl -----------------------------------------------------------------------
     dnl GStreamer
 if test "$wxUSE_MEDIACTRL" = "yes"; then
     dnl -----------------------------------------------------------------------
     dnl GStreamer
@@ -6762,77 +6767,57 @@ if test "$wxUSE_MEDIACTRL" = "yes"; then
         wxUSE_GSTREAMER="yes"
 
         dnl -------------------------------------------------------------------
         wxUSE_GSTREAMER="yes"
 
         dnl -------------------------------------------------------------------
-        dnl Test for gstreamer module from pkg-config
+        dnl Test for at least 0.8 gstreamer module from pkg-config
+        dnl Even totem doesn't accept 0.9 evidently.
+        dnl
+        dnl So, we first check to see if 0.10 if available - if not we
+        dnl try the older 0.8 version
         dnl -------------------------------------------------------------------
         dnl -------------------------------------------------------------------
-        PKG_CHECK_MODULES(GSTREAMER, gstreamer-0.8,
+        GST_VERSION_MAJOR=0
+        GST_VERSION_MINOR=10
+        GST_VERSION_RELEASE=0
+        GSTREAMER_REQ=$GST_VERSION_MAJOR.$GST_VERSION_MINOR.$GST_VERSION_RELEASE
+        GST_MAJORMINOR=$GST_VERSION_MAJOR.$GST_VERSION_MINOR
+
+        if test "$wxUSE_GSTREAMER8" = "no"; then
+            PKG_CHECK_MODULES(GST, gstreamer-$GST_MAJORMINOR
+                               gstreamer-plugins-base-$GST_MAJORMINOR
+                               gconf-2.0,
         [
         [
-            CPPFLAGS="$GSTREAMER_CFLAGS $CPPFLAGS"
-            LIBS="$LIBS $GSTREAMER_LIBS -lgstplay-0.8"
+                    CPPFLAGS="$GST_CFLAGS $CPPFLAGS"
+                    LIBS="$LIBS $GST_LIBS -lgstinterfaces-$GST_MAJORMINOR"
         ],
         [
         ],
         [
-            AC_MSG_WARN([GStreamer installation not found])
-            wxUSE_GSTREAMER="no"
+                    GST_VERSION_MINOR=8
         ])
         ])
-
-        dnl -------------------------------------------------------------------
-        dnl Perform a check for a GStreamer element using gst-inspect
-        dnl Thomas Vander Stichele <thomas at apestaart dot org>
-        dnl Last modification: 25/01/2005
-        dnl
-        dnl AM_GST_ELEMENT_CHECK(ELEMENT-NAME, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND)
-        dnl -------------------------------------------------------------------
-        AC_DEFUN([AM_GST_ELEMENT_CHECK],
-        [
-        if test "x$GST_INSPECT" == "x"; then
-            AC_CHECK_PROG(GST_INSPECT, gst-inspect, gst-inspect, [])
-        fi
-
-        if test "x$GST_INSPECT" != "x"; then
-            AC_MSG_CHECKING(GStreamer element $1)
-            if [ $GST_INSPECT $1 > /dev/null 2> /dev/null ]; then
-            AC_MSG_RESULT(found.)
-            $2
             else
             else
-            AC_MSG_RESULT(not found.)
-            $3
-            fi
+            GST_VERSION_MINOR=8
         fi
         fi
-        ])
 
 
-        dnl -------------------------------------------------------------------
-        dnl Test for x video sink (video useless without)
-        dnl -------------------------------------------------------------------
-        AM_GST_ELEMENT_CHECK(xvimagesink,[],
-                        [
-                            wxUSE_GSTREAMER="no"
-                            AC_MSG_WARN([x video sink not found - cannot use GStreamer])
-                        ])
+        GSTREAMER_REQ=$GST_VERSION_MAJOR.$GST_VERSION_MINOR.$GST_VERSION_RELEASE
+        GST_MAJORMINOR=$GST_VERSION_MAJOR.$GST_VERSION_MINOR
 
 
-        dnl -------------------------------------------------------------------
-        dnl Check for gstplay-0.8 lib and corresponding x overlay header
-        dnl -------------------------------------------------------------------
-        AC_CHECK_HEADER(gst/xoverlay/xoverlay.h, [],
+        if test x$GST_VERSION_MINOR = x8; then
+            PKG_CHECK_MODULES(GST, gstreamer-$GST_MAJORMINOR
+                gstreamer-interfaces-$GST_MAJORMINOR
+                gstreamer-gconf-$GST_MAJORMINOR,
                         [
                         [
-                            wxUSE_GSTREAMER="no"
-                            AC_MSG_WARN([xoverlay header not found, cannot use GStreamer])
+                    CPPFLAGS="$GST_CFLAGS $CPPFLAGS"
+                    LIBS="$LIBS $GST_LIBS"
                         ],
                         ],
-                        [#include <gst/gst.h>])
-
-        AC_MSG_CHECKING([for gstplay 0.8])
-        WX_PATH_FIND_LIBRARIES([$SEARCH_LIB],gstplay-0.8)
-
-        if test "$ac_find_libraries" = "" ; then
-            AC_MSG_RESULT([no])
+                [
+                    AC_MSG_WARN([Proper GStreamer .8/.10 installation not found])
             wxUSE_GSTREAMER="no"
             wxUSE_GSTREAMER="no"
-        else
-            AC_MSG_RESULT([yes])
+                ])
         fi
 
         fi
 
+
         if test "$wxUSE_GSTREAMER" = "yes"; then
             AC_DEFINE(wxUSE_GSTREAMER)
             AC_MSG_RESULT([GStreamer detection successful])
         fi
     fi
         if test "$wxUSE_GSTREAMER" = "yes"; then
             AC_DEFINE(wxUSE_GSTREAMER)
             AC_MSG_RESULT([GStreamer detection successful])
         fi
     fi
+    USE_MEDIA=1
     SAMPLES_SUBDIRS="$SAMPLES_SUBDIRS mediaplayer"
     AC_DEFINE(wxUSE_MEDIACTRL)
 fi
     SAMPLES_SUBDIRS="$SAMPLES_SUBDIRS mediaplayer"
     AC_DEFINE(wxUSE_MEDIACTRL)
 fi
diff --git a/docs/latex/wx/activexcontainer.tex b/docs/latex/wx/activexcontainer.tex
new file mode 100644 (file)
index 0000000..fa3e1e8
--- /dev/null
@@ -0,0 +1,236 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Name:        activexcontainer.tex
+%% Purpose:     wxActiveXContainer docs
+%% Author:      Ryan Norton <wxprojects@comcast.net>
+%% Modified by:
+%% Created:     01/30/2005
+%% RCS-ID:      $Id$
+%% Copyright:   (c) Ryan Norton
+%% License:     wxWindows license
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\section{\class{wxActiveXContainer}}\label{wxactivexcontainer}
+
+wxActiveXContainer is a host for an activex control on Windows (and
+as such is a platform-specific class). Note that the HWND that the class
+contains is the actual HWND of the activex control so using dynamic events
+and connecting to wxEVT\_SIZE, for example, will recieve the actual size
+message sent to the control.
+
+It is somewhat similar to the ATL class CAxWindow in operation.
+
+The size of the activex control's content is generally gauranteed to be that
+of the client size of the parent of this wxActiveXContainer.
+
+You can also process activex events through wxEVT\_ACTIVEX or the
+corresponding message map macro EVT\_ACTIVEX.
+
+\wxheading{See also}
+
+\helpref{wxActiveXEvent}{wxactivexevent}
+
+\wxheading{Derived from}
+
+\helpref{wxControl}{wxcontrol}
+
+\wxheading{Include files}
+
+<wx/msw/ole/activex.h>
+
+\wxheading{Example}
+
+This is an example of how to use the Adobe Acrobat Reader ActiveX control to read PDF files
+(requires Acrobat Reader 4 and up). Controls like this are typically found and dumped from
+OLEVIEW.exe that is distributed with Microsoft Visual C++. This example also demonstrates
+how to create a backend for \helpref{wxMediaCtrl}{wxmediactrl}.
+
+\begin{verbatim}
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// wxPDFMediaBackend
+//
+// http://partners.adobe.com/public/developer/en/acrobat/sdk/pdf/iac/IACOverview.pdf
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#include "wx/mediactrl.h"       // wxMediaBackendCommonBase
+#include "wx/msw/ole/activex.h" // wxActiveXContainer
+#include "wx/msw/ole/automtn.h" // wxAutomationObject
+
+const IID DIID__DPdf = {0xCA8A9781,0x280D,0x11CF,{0xA2,0x4D,0x44,0x45,0x53,0x54,0x00,0x00}};
+const IID DIID__DPdfEvents = {0xCA8A9782,0x280D,0x11CF,{0xA2,0x4D,0x44,0x45,0x53,0x54,0x00,0x00}};
+const CLSID CLSID_Pdf = {0xCA8A9780,0x280D,0x11CF,{0xA2,0x4D,0x44,0x45,0x53,0x54,0x00,0x00}};
+
+class WXDLLIMPEXP_MEDIA wxPDFMediaBackend : public wxMediaBackendCommonBase
+{
+public:
+    wxPDFMediaBackend() : m_pAX(NULL) {}
+    virtual ~wxPDFMediaBackend()
+    {
+        if(m_pAX)
+        {
+            m_pAX->DissociateHandle();
+            delete m_pAX;
+        }
+    }
+    virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
+                                     wxWindowID id,
+                                     const wxPoint& pos,
+                                     const wxSize& size,
+                                     long style,
+                                     const wxValidator& validator,
+                                     const wxString& name)
+    {
+        IDispatch* pDispatch;
+        if( ::CoCreateInstance(CLSID_Pdf, NULL,
+                                  CLSCTX_INPROC_SERVER,
+                                  DIID__DPdf, (void**)&pDispatch) != 0 )
+            return false;
+
+        m_PDF.SetDispatchPtr(pDispatch); // wxAutomationObject will release itself
+
+        if ( !ctrl->wxControl::Create(parent, id, pos, size,
+                                (style & ~wxBORDER_MASK) | wxBORDER_NONE,
+                                validator, name) )
+            return false;
+
+        m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
+        m_pAX = new wxActiveXContainer(ctrl,
+                    DIID__DPdf,
+                    pDispatch);
+
+        wxPDFMediaBackend::ShowPlayerControls(wxMEDIACTRLPLAYERCONTROLS_NONE);
+        return true;
+    }
+
+    virtual bool Play()
+    {
+        return true;
+    }
+    virtual bool Pause()
+    {
+        return true;
+    }
+    virtual bool Stop()
+    {
+        return true;
+    }
+
+    virtual bool Load(const wxString& fileName)
+    {
+        if(m_PDF.CallMethod(wxT("LoadFile"), fileName).GetBool())
+        {
+            m_PDF.CallMethod(wxT("setCurrentPage"), wxVariant((long)0));
+            NotifyMovieLoaded(); // initial refresh
+            wxSizeEvent event;
+            m_pAX->OnSize(event);
+            return true;
+        }
+
+        return false;
+    }
+    virtual bool Load(const wxURI& location)
+    {
+        return m_PDF.CallMethod(wxT("LoadFile"), location.BuildUnescapedURI()).GetBool();
+    }
+    virtual bool Load(const wxURI& WXUNUSED(location),
+                      const wxURI& WXUNUSED(proxy))
+    {
+        return false;
+    }
+
+    virtual wxMediaState GetState()
+    {
+        return wxMEDIASTATE_STOPPED;
+    }
+
+    virtual bool SetPosition(wxLongLong where)
+    {
+        m_PDF.CallMethod(wxT("setCurrentPage"), wxVariant((long)where.GetValue()));
+        return true;
+    }
+    virtual wxLongLong GetPosition()
+    {
+        return 0;
+    }
+    virtual wxLongLong GetDuration()
+    {
+        return 0;
+    }
+
+    virtual void Move(int WXUNUSED(x), int WXUNUSED(y),
+                      int WXUNUSED(w), int WXUNUSED(h))
+    {
+    }
+    wxSize GetVideoSize() const
+    {
+        return wxDefaultSize;
+    }
+
+    virtual double GetPlaybackRate()
+    {
+        return 0;
+    }
+    virtual bool SetPlaybackRate(double)
+    {
+        return false;
+    }
+
+    virtual double GetVolume()
+    {
+        return 0;
+    }
+    virtual bool SetVolume(double)
+    {
+        return false;
+    }
+
+    virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags)
+    {
+        if(flags)
+        {
+            m_PDF.CallMethod(wxT("setShowToolbar"), true);
+            m_PDF.CallMethod(wxT("setShowScrollbars"), true);
+        }
+        else
+        {
+            m_PDF.CallMethod(wxT("setShowToolbar"), false);
+            m_PDF.CallMethod(wxT("setShowScrollbars"), false);
+        }
+
+        return true;
+    }
+
+    wxActiveXContainer* m_pAX;
+    wxAutomationObject m_PDF;
+
+    DECLARE_DYNAMIC_CLASS(wxPDFMediaBackend)
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxPDFMediaBackend, wxMediaBackend);
+\end{verbatim}
+
+Put this in one of your existant source files and then create a wxMediaCtrl with
+\begin{verbatim}
+//[this] is the parent window, "myfile.pdf" is the PDF file to open
+wxMediaCtrl* mymediactrl = new wxMediaCtrl(this, wxT("myfile.pdf"), wxID_ANY,
+                                           wxDefaultPosition, wxSize(300,300),
+                                           0, wxT("wxPDFMediaBackend"));
+\end{verbatim}
+
+
+\latexignore{\rtfignore{\wxheading{Members}}}
+
+\membersection{wxActiveXContainer::wxActiveXContainer}\label{wxactivexcontainerwxactivexcontainer}
+
+\func{}{wxActiveXContainer}{
+        \param{wxWindow* }{parent},
+        \param{REFIID }{iid},
+        \param{IUnknown* }{pUnk},
+                   }
+
+Creates this activex container.
+
+\docparam{parent}{parent of this control.  Must not be NULL.}
+\docparam{iid}{COM IID of pUnk to query. Must be a valid interface to an activex control.}
+\docparam{pUnk}{Interface of activex control}
+
diff --git a/docs/latex/wx/activexevt.tex b/docs/latex/wx/activexevt.tex
new file mode 100644 (file)
index 0000000..301b865
--- /dev/null
@@ -0,0 +1,75 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Name:        activexevt.tex
+%% Purpose:     wxActiveXEvent docs
+%% Author:      Ryan Norton <wxprojects@comcast.net>
+%% Modified by:
+%% Created:     01/30/2005
+%% RCS-ID:      $Id$
+%% Copyright:   (c) Ryan Norton
+%% License:     wxWindows license
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\section{\class{wxActiveXEvent}}\label{wxactivexevent}
+
+An event class for handling activex events passed from
+\helpref{wxActiveXContainer}{wxactivexcontainer}. ActiveX events are basically
+a function call with the parameters passed through an array of wxVariants along
+with a return value that is a wxVariant itself. What type the parameters or
+return value are depends on the context (i.e. what the .idl specifies).
+
+Note that unlike the third party wxActiveX function names are not supported.
+
+\wxheading{Derived from}
+
+\helpref{wxCommandEvent}{wxcommandevent}
+
+\wxheading{Include files}
+
+<wx/msw/ole/activex.h>
+
+\wxheading{Event table macros}
+
+\twocolwidtha{7cm}
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf EVT\_ACTIVEX(func)}}{
+Sent when the activex control hosted by \helpref{wxActiveXContainer}{wxactivexcontainer}
+recieves an activex event.}
+\end{twocollist}
+
+\latexignore{\rtfignore{\wxheading{Members}}}
+
+\membersection{wxActiveXEvent::ParamCount}\label{wxactivexeventparamcount}
+
+\constfunc{int}{ParamCount}{\void}
+
+Obtains the number of parameters passed through the activex event.
+
+
+\membersection{wxActiveXEvent::ParamType}\label{wxactivexeventparamtype}
+
+\constfunc{wxString}{ParamType}{\param{int }{idx}}
+
+Obtains the param type of the param number idx specifies as a string.
+
+
+\membersection{wxActiveXEvent::ParamName}\label{wxactivexeventparamname}
+
+\constfunc{wxString}{ParamName}{\param{int }{idx}}
+
+Obtains the param name of the param number idx specifies as a string.
+
+
+\membersection{wxActiveXEvent::operator[]}\label{wxactivexeventoparray}
+
+\func{wxVariant&}{operator[]}{\param{int }{idx}}
+
+Obtains the actual parameter value specified by idx.
+
+
+\membersection{wxActiveXEvent::GetDispatchId}\label{wxactivexeventgetdispatchid}
+
+\constfunc{DISPID}{GetDispatchId}{\param{int }{idx}}
+
+Returns the dispatch id of this activex event. This is the numeric value from
+the .idl file specified by the id().
+
index 158edda4be8ade8b1e41b97c58096030fee58339..0deb6b639e4510172b467fae78d601d4f1f5768f 100644 (file)
@@ -8,6 +8,8 @@
 \input accel.tex
 \input accessible.tex
 \input activevt.tex
 \input accel.tex
 \input accessible.tex
 \input activevt.tex
+\input activexcontainer.tex
+\input activexevt.tex
 \input app.tex
 \input archive.tex
 \input array.tex
 \input app.tex
 \input archive.tex
 \input array.tex
index 155652ae6fd9e391f441ceca32f01e9984cef913..ef6c49a0556874e74bce2fec9408e830fa6f607e 100644 (file)
@@ -18,6 +18,10 @@ wxMediaCtrl uses native backends to render media, for example on Windows
 there is a ActiveMovie/DirectShow backend, and on Macintosh there is a 
 QuickTime backend.
 
 there is a ActiveMovie/DirectShow backend, and on Macintosh there is a 
 QuickTime backend.
 
+\wxheading{See also}
+
+\helpref{wxMediaEvent}{wxmediaevent}
+
 \wxheading{Derived from}
 
 \helpref{wxControl}{wxcontrol}
 \wxheading{Derived from}
 
 \helpref{wxControl}{wxcontrol}
@@ -28,6 +32,7 @@ QuickTime backend.
 
 \latexignore{\rtfignore{\wxheading{Members}}}
 
 
 \latexignore{\rtfignore{\wxheading{Members}}}
 
+
 \membersection{Rendering media}\label{renderingmediawxmediactrl}
 
 Depending upon the backend, wxMediaCtrl can render
 \membersection{Rendering media}\label{renderingmediawxmediactrl}
 
 Depending upon the backend, wxMediaCtrl can render
@@ -48,6 +53,7 @@ capabilities of the backend.  For example, QuickTime cannot set
 the playback rate of certain streaming media - while DirectShow is 
 slightly more flexible in that regard.
 
 the playback rate of certain streaming media - while DirectShow is 
 slightly more flexible in that regard.
 
+
 \membersection{Operation}\label{operationwxmediactrl}
 
 When wxMediaCtrl plays a file, it plays until the stop position
 \membersection{Operation}\label{operationwxmediactrl}
 
 When wxMediaCtrl plays a file, it plays until the stop position
@@ -86,6 +92,50 @@ because some streams are not seekable, and when stop is called
 on them they return to the beginning, thus wxMediaCtrl tries
 to keep consistant for all types of media.
 
 on them they return to the beginning, thus wxMediaCtrl tries
 to keep consistant for all types of media.
 
+Note that when changing the state of the media through Play()
+and other methods, the media may not actually be in the
+wxMEDIASTATE\_PLAYING, for example. If you are relying on the
+media being in certain state catch the event relevant to the state.
+See \helpref{wxMediaEvent}{wxmediaevent} for the kinds of events
+that you can catch.
+
+
+\membersection{Video size}\label{videosizewxmediactrl}
+
+By default, wxMediaCtrl will scale the size of the video to the
+requested amount passed to either it's constructor or Create().
+After calling Load or performing an equivilant operation, you
+can subsequently obtain the "real" size of the video (if there
+is any) by calling GetBestSize(). Note that the actual result
+on the display will be slightly different when ShowPlayerControls
+is activated and the actual video size will be less then
+specified due to the extra controls provided by the native toolkit.
+In addition, the backend may modify GetBestSize() to include the
+size of the extra controls - so if you want the real size of the
+video just disable ShowPlayerControls().
+
+The idea with setting GetBestSize to the size of the video is
+that GetBestSize is a wxWindow-derived function that is called
+when sizers on a window recalculate. What this means is that
+if you use sizers by default the video will show in it's
+original size without any extra assistance needed from the user.
+
+
+\membersection{Player controls}\label{playercontrolswxmediactrl}
+
+Normally, when you use wxMediaCtrl it is just a window for the video to
+play in.  However, some toolkits have their own media player interface.
+For example, QuickTime generally has a bar below the video with a slider.
+A special feature available to wxMediaCtrl, you can use the toolkit's interface instead of
+making your own by using the \helpref{ShowPlayerControls()}{wxmediactrlshowplayercontrols}
+function.  There are several options for the flags parameter, with
+the two general flags being wxMEDIACTRLPLAYERCONTROLS\_NONE which turns off
+the native interface, and wxMEDIACTRLPLAYERCONTROLS\_DEFAULT which lets
+wxMediaCtrl decide what native controls on the interface. Be sure to review
+the caveats outlined in \helpref{Video size}{videosizewxmediactrl} before
+doing so.
+
+
 \membersection{Choosing a backend}\label{choosingbackendwxmediactrl}
 
 Generally, you should almost certainly leave this part up to
 \membersection{Choosing a backend}\label{choosingbackendwxmediactrl}
 
 Generally, you should almost certainly leave this part up to
@@ -99,17 +149,48 @@ The following are valid backend identifiers -
 \twocolwidtha{7cm}
 \begin{twocollist}\itemsep=0pt
 \twocolitem{{\bf wxMEDIABACKEND\_DIRECTSHOW}}{ 
 \twocolwidtha{7cm}
 \begin{twocollist}\itemsep=0pt
 \twocolitem{{\bf wxMEDIABACKEND\_DIRECTSHOW}}{ 
-Use ActiveMovie/DirectShow.  Requires wxUSE\_DIRECTSHOW to be 
-enabled, requires linkage with the static library strmiids.lib,
-and is available on Windows Only.}
+Use ActiveMovie/DirectShow.  Uses the native ActiveMovie
+(I.E. DirectShow) control. Default backend on Windows and
+supported by nearly all Windows versions, even some
+Windows CE versions. May display a windows media player
+logo while inactive. }
 \twocolitem{{\bf wxMEDIABACKEND\_QUICKTIME}}{
 \twocolitem{{\bf wxMEDIABACKEND\_QUICKTIME}}{
-Use QuickTime.  Windows and Mac Only. NOTE: On Mac Systems lower than OSX 10.2 this defaults to emulating window positioning and suffers from several bugs, including not working correctly embedded in a wxNotebook. }
-\twocolitem{{\bf wxMEDIABACKEND\_MCI}}{
-Use Media Command Interface.  Windows Only. }
+Use QuickTime.  Mac Only.
+WARNING: May not working correctly embedded in a wxNotebook.
+}
 \twocolitem{{\bf wxMEDIABACKEND\_GSTREAMER}}{
 \twocolitem{{\bf wxMEDIABACKEND\_GSTREAMER}}{
-Use GStreamer.  Unix Only. }
+Use GStreamer.  Unix Only. Requires GStreamer 0.8 along
+with at the very least the xvimagesink, xoverlay, and
+gst-play modules of gstreamer to function. You need the correct
+modules to play the relavant files, for example the mad module
+to play mp3s, etc.}
+\twocolitem{{\bf wxMEDIABACKEND\_WMP10}}{
+Uses Windows Media Player 10 (Windows only) - works on mobile
+machines with Windows Media Player 10 and desktop machines with
+either Windows Media Player 9 or 10
+}
 \end{twocollist}
 
 \end{twocollist}
 
+Note that other backends such as wxMEDIABACKEND\_MCI can now be
+found at wxCode.
+
+\membersection{Creating a backend}\label{creatingabackendwxmediactrl}
+
+Creating a backend for wxMediaCtrl is a rather simple process. Simply derive
+from wxMediaBackendCommonBase and implement the methods you want. The methods
+in wxMediaBackend correspond to those in wxMediaCtrl except for CreateControl
+which does the actual creation of the control, in cases where a custom control
+is not needed you may simply call wxControl::Create.
+
+You need to make sure to use the DECLARE\_CLASS and IMPLEMENT\_CLASS macros.
+
+The only real tricky part is that you need to make sure the file in compiled
+in, which if there are just backends in there will not happen and you may need
+to use a force link hack (see http://www.wxwidgets.org/wiki/index.php/RTTI).
+
+This is a rather simple example of how to create a backend in the
+\helpref{wxActiveXContainer}{wxactivexcontainer} documentation.
+
 \membersection{wxMediaCtrl::wxMediaCtrl}\label{wxmediactrlwxmediactrl}
 
 \func{}{wxMediaCtrl}{\void}
 \membersection{wxMediaCtrl::wxMediaCtrl}\label{wxmediactrlwxmediactrl}
 
 \func{}{wxMediaCtrl}{\void}
@@ -173,25 +254,38 @@ wxMediaCtrl figure it out.}
 \docparam{name}{Window name.}
 
 
 \docparam{name}{Window name.}
 
 
-\membersection{wxMediaCtrl::Length}\label{wxmediactrlgetduration}
+\membersection{wxMediaCtrl::GetBestSize}\label{wxmediactrlgetbestsize}
 
 
-\func{wxFileOffset}{GetDuration}{\void}
+\func{wxSize}{GetBestSize}{\void}
 
 
-Obtains the length - the total amount of time the movie has in milliseconds.
+Obtains the best size relative to the original/natural size of the
+video, if there is any. See \helpref{Video size}{videosizewxmediactrl}
+for more information.
 
 
 
 
-\membersection{wxMediaCtrl::Tell}\label{wxmediactrlgetposition}
+\membersection{wxMediaCtrl::GetPlaybackRate}\label{wxmediactrlgetplaybackrate}
 
 
-\func{wxFileOffset}{GetPosition}{\void}
+\func{double}{GetPlaybackrate}{\void}
 
 
-Obtains the current position in time within the movie in milliseconds.
+Obtains the playback rate, or speed of the media. \tt{1.0} represents normal
+speed, while \tt{2.0} represents twice the normal speed of the media, for
+example. Not supported on the GStreamer (Unix) backend.
+Returns 0 on failure.
+
+
+\membersection{wxMediaCtrl::GetVolume}\label{wxmediactrlgetvolume}
+
+\func{double}{GetVolume}{\void}
+
+Gets the volume of the media from a 0.0 to 1.0 range. Note that due to rounding
+and other errors this may not be the exact value sent to SetVolume.
 
 
 \membersection{wxMediaCtrl::GetState}\label{wxmediactrlgetstate}
 
 \func{wxMediaCtrlState}{GetState}{\void}
 
 
 
 \membersection{wxMediaCtrl::GetState}\label{wxmediactrlgetstate}
 
 \func{wxMediaCtrlState}{GetState}{\void}
 
-Obtains the state the playback of the movie is in - 
+Obtains the state the playback of the media is in -
 
 \twocolwidtha{7cm}
 \begin{twocollist}\itemsep=0pt
 
 \twocolwidtha{7cm}
 \begin{twocollist}\itemsep=0pt
@@ -201,6 +295,13 @@ Obtains the state the playback of the movie is in -
 \end{twocollist}
 
 
 \end{twocollist}
 
 
+\membersection{wxMediaCtrl::Length}\label{wxmediactrllength}
+
+\func{wxFileOffset}{Length}{\void}
+
+Obtains the length - the total amount of time the movie has in milliseconds.
+
+
 \membersection{wxMediaCtrl::Load}\label{wxmediactrlload}
 
 \func{bool}{Load}{\param{const wxString\& }{fileName}}
 \membersection{wxMediaCtrl::Load}\label{wxmediactrlload}
 
 \func{bool}{Load}{\param{const wxString\& }{fileName}}
@@ -210,9 +311,31 @@ Loads the file that \tt{fileName} refers to.  Returns false if loading fails.
 
 \membersection{wxMediaCtrl::Load}\label{wxmediactrlloaduri}
 
 
 \membersection{wxMediaCtrl::Load}\label{wxmediactrlloaduri}
 
-\func{bool}{Load}{\param{const wxURI\& }{location}}
+\func{bool}{Load}{\param{const wxURI\& }{uri}}
+
+Loads the location that \tt{uri} refers to.  Note that this is very implementation-dependant, although HTTP URI/URLs are generally supported, for example. Returns false if loading fails.
+
+
+\membersection{wxMediaCtrl::Load}\label{wxmediactrlloaduriwithproxy}
+
+\func{bool}{Load}{\param{const wxURI\& }{uri}, \param{const wxURI\& }{proxy}}
+
+Loads the location that \tt{uri} refers to with the proxy \tt{proxy}. Not implemented on most backends so it should be called with caution. Returns false if loading fails.
+
+
+\membersection{wxMediaCtrl::LoadURI}\label{wxmediactrlloaduriliteral}
+
+\func{bool}{LoadURI}{\param{const wxURI\& }{uri}}
+
+Same as \helpref{Load}{wxmediactrlloaduri}. Kept for wxPython compatability.
+
+
+\membersection{wxMediaCtrl::LoadURIWithProxy}\label{wxmediactrlloaduriwithproxyliteral}
+
+\func{bool}{LoadURIWithProxy}{\param{const wxURI\& }{uri}, \param{const wxURI\& }{proxy}}
+
+Same as \helpref{Load}{wxmediactrlloaduriwithproxy}. Kept for wxPython compatability.
 
 
-Loads the url that \tt{location} refers to.  Returns false if loading fails.  
 
 \membersection{wxMediaCtrl::Pause}\label{wxmediactrlpause}
 
 
 \membersection{wxMediaCtrl::Pause}\label{wxmediactrlpause}
 
@@ -235,54 +358,65 @@ Resumes playback of the movie.
 Seeks to a position within the movie.
 
 
 Seeks to a position within the movie.
 
 
-\membersection{wxMediaCtrl::Stop}\label{wxmediactrlstop}
-
-\func{bool}{Stop}{\void}
+\membersection{wxMediaCtrl::SetPlaybackRate}\label{wxmediactrlsetplaybackrate}
 
 
-Stops the media.
+\func{bool}{SetPlaybackRate}{\param{double }{dRate}}
 
 
-See \helpref{Operation}{operationwxmediactrl} for an overview of how stopping works.
+Sets the playback rate, or speed of the media, to that referred by \tt{dRate}.
+\tt{1.0} represents normal speed, while \tt{2.0} represents twice the normal
+speed of the media, for example. Not supported on the GStreamer (Unix) backend.
+Returns true if successful.
 
 
 \membersection{wxMediaCtrl::SetVolume}\label{wxmediactrlsetvolume}
 
 \func{bool}{SetVolume}{\param{double }{dVolume}}
 
 
 
 \membersection{wxMediaCtrl::SetVolume}\label{wxmediactrlsetvolume}
 
 \func{bool}{SetVolume}{\param{double }{dVolume}}
 
-Sets the volume of the media from a 0.0 to 1.0 range.
-
+Sets the volume of the media from a 0.0 to 1.0 range to that referred
+by \tt{dVolume}.  \tt{1.0} represents full volume, while \tt{0.5}
+represents half (50 percent) volume, for example.  Note that this may not be
+exact due to conversion and rounding errors, although setting the volume to
+full or none is always exact. Returns true if successful.
 
 
-\membersection{wxMediaCtrl::GetVolume}\label{wxmediactrlgetvolume}
-
-\func{double}{GetVolume}{\void}
 
 
-Gets the volume of the media from a 0.0 to 1.0 range.
+\membersection{wxMediaCtrl::ShowPlayerControls}\label{wxmediactrlshowplayercontrols}
 
 
+\func{bool}{ShowPlayerControls}{\param{wxMediaCtrlPlayerControls }{flags = wxMEDIACTRLPLAYERCONTROLS\_DEFAULT}}
 
 
-\membersection{wxMediaCtrl::GetPlaybackRate}\label{wxmediactrlgetplaybackrate}
+A special feature to wxMediaCtrl. Applications using native toolkits such as
+QuickTime usually have a scrollbar, play button, and more provided to
+them by the toolkit. By default wxMediaCtrl does not do this. However, on
+the directshow and quicktime backends you can show or hide the native controls
+provided by the underlying toolkit at will using ShowPlayerControls. Simply
+calling the function with default parameters tells wxMediaCtrl to use the
+default controls provided by the toolkit. The function takes a
+\tt{wxMediaCtrlPlayerControls} enumeration as follows:
 
 
-\func{double}{GetPlaybackrate}{\void}
+\twocolwidtha{7cm}
+\begin{twocollist}\itemsep=0pt
+\twocolitem{{\bf wxMEDIACTRLPLAYERCONTROLS\_NONE}}{No controls. return wxMediaCtrl to it's default state.}
+\twocolitem{{\bf wxMEDIACTRLPLAYERCONTROLS\_STEP}}{Step controls like fastfoward, step one frame etc.}
+\twocolitem{{\bf wxMEDIACTRLPLAYERCONTROLS\_VOLUME}}{Volume controls like the speaker icon, volume slider, etc.}
+\twocolitem{{\bf wxMEDIACTRLPLAYERCONTROLS\_DEFAULT}}{Default controls for the toolkit. Currently a typedef for wxMEDIACTRLPLAYERCONTROLS\_STEP and wxMEDIACTRLPLAYERCONTROLS\_VOLUME.}
+\end{twocollist}
 
 
-Gets the playback rate of the media; for example 2.0 is double speed.
-Not implemented on MCI or GStreamer.
+For more see \helpref{Player controls}{playercontrolswxmediactrl}. Currently
+only implemented on the QuickTime and DirectShow backends. The function
+returns true on success.
 
 
 
 
-\membersection{wxMediaCtrl::SetPlaybackRate}\label{wxmediactrlsetplaybackrate}
+\membersection{wxMediaCtrl::Stop}\label{wxmediactrlstop}
 
 
-\func{bool}{SetPlaybackrate}{\param{double }{dVolume}}
+\func{bool}{Stop}{\void}
 
 
-Sets the rate that the media plays; for example 0.5 is half speed.
+Stops the media.
 
 
+See \helpref{Operation}{operationwxmediactrl} for an overview of how
+stopping works.
 
 
-\membersection{wxMediaCtrl::ShowPlayerControls}\label{wxmediactrlshowplayercontrols}
 
 
-\func{bool}{ShowPlayerControls}{\param{wxMediaCtrlPlayerControls }{flags}}
+\membersection{wxMediaCtrl::Tell}\label{wxmediactrlgetposition}
 
 
-Normally, when you use wxMediaCtrl it is just a window for the video to 
-play in.  However, platforms generally have their own media player interface,
-like quicktime has a bar below the video with a slider etc..  If you want that native 
-interface instead of making your own use this function.  There are several options
-for the flags parameter, however you can look at the mediactrl header for these. 
-The two general flags are wxMEDIACTRLPLAYERCONTROLS\_NONE which turns off the 
-native interface, and wxMEDIACTRLPLAYERCONTROLS\_DEFAULT which lets wxMediaCtrl
-decide what native controls on the interface.
+\func{wxFileOffset}{Tell}{\void}
 
 
+Obtains the current position in time within the movie in milliseconds.
index 937dd514189e05e0aa447de2e7fd4e3107f83e97..23475110468a44b7bd356f741f12dc2b7c916fdf 100644 (file)
@@ -25,10 +25,26 @@ Event \helpref{wxMediaCtrl}{wxmediactrl} uses.
 
 \twocolwidtha{7cm}
 \begin{twocollist}\itemsep=0pt
 
 \twocolwidtha{7cm}
 \begin{twocollist}\itemsep=0pt
-\twocolitem{{\bf EVT\_MEDIA\_LOADED(func)}}{Sent when a media has loaded enough data that it can start playing.}
+\twocolitem{{\bf EVT\_MEDIA\_LOADED(func)}}{
+Sent when a media has loaded enough data that it can start playing.}
 \twocolitem{{\bf EVT\_MEDIA\_STOP(func)}}{
 \twocolitem{{\bf EVT\_MEDIA\_STOP(func)}}{
-Triggerred right before the media stops.  You can Veto this event to prevent it from stopping, causing it to continue playing - even if it has reached that end of the media. }
-\twocolitem{{\bf EVT\_MEDIA\_FINISHED(func)}}{Sent when a media has finished playing in a \helpref{wxMediaCtrl}{wxmediactrl}.  Note that if you connect to this event and don't skip it, it will override the looping behaviour of the media control.}
+Send when a media has switched to the wxMEDIASTATE\_STOPPED state.
+You may be able to Veto this event to prevent it from stopping,
+causing it to continue playing - even if it has reached that end of the media
+(note that this may not have the desired effect - if you want to loop the
+media, for example, catch the EVT\_MEDIA\_FINISHED and play there instead). }
+\twocolitem{{\bf EVT\_MEDIA\_FINISHED(func)}}{
+Sent when a media has finished playing in a \helpref{wxMediaCtrl}{wxmediactrl}.
+}
+\twocolitem{{\bf EVT\_MEDIA\_STATECHANGED(func)}}{
+Send when a media has switched its state (from any media state).
+}
+\twocolitem{{\bf EVT\_MEDIA\_PLAY(func)}}{
+Send when a media has switched to the wxMEDIASTATE\_PLAYING state.
+}
+\twocolitem{{\bf EVT\_MEDIA\_PAUSE(func)}}{
+Send when a media has switched to the wxMEDIASTATE\_PAUSED state.
+}
 \end{twocollist}
 
 \latexignore{\rtfignore{\wxheading{Members}}}
 \end{twocollist}
 
 \latexignore{\rtfignore{\wxheading{Members}}}
index e03d509968b1c3bcf4caa25f048da9ac62d9efc6..9015d421ff41f6b66083ca155106becc35c03c95 100644 (file)
@@ -22,6 +22,9 @@
 // ----------------------------------------------------------------------------
 // Pre-compiled header stuff
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // Pre-compiled header stuff
 // ----------------------------------------------------------------------------
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
+#pragma interface "mediactrl.h"
+#endif
 
 #include "wx/defs.h"
 
 
 #include "wx/defs.h"
 
@@ -71,7 +74,8 @@ enum wxMediaCtrlPlayerControls
 #define wxMEDIABACKEND_MCI          wxT("wxMCIMediaBackend")
 #define wxMEDIABACKEND_QUICKTIME    wxT("wxQTMediaBackend")
 #define wxMEDIABACKEND_GSTREAMER    wxT("wxGStreamerMediaBackend")
 #define wxMEDIABACKEND_MCI          wxT("wxMCIMediaBackend")
 #define wxMEDIABACKEND_QUICKTIME    wxT("wxQTMediaBackend")
 #define wxMEDIABACKEND_GSTREAMER    wxT("wxGStreamerMediaBackend")
-
+#define wxMEDIABACKEND_REALPLAYER   wxT("wxRealPlayerMediaBackend")
+#define wxMEDIABACKEND_WMP10        wxT("wxWMP10MediaBackend")
 
 // ----------------------------------------------------------------------------
 //
 
 // ----------------------------------------------------------------------------
 //
@@ -190,14 +194,17 @@ public:
     wxFileOffset Tell(); //FIXME: This should be const
     wxFileOffset Length(); //FIXME: This should be const
 
     wxFileOffset Tell(); //FIXME: This should be const
     wxFileOffset Length(); //FIXME: This should be const
 
+#if wxABI_VERSION >= 20601 /* 2.6.1+ only */
     double GetPlaybackRate();           //All but MCI & GStreamer
     bool SetPlaybackRate(double dRate); //All but MCI & GStreamer
     double GetPlaybackRate();           //All but MCI & GStreamer
     bool SetPlaybackRate(double dRate); //All but MCI & GStreamer
+#endif
 
 
+#if wxABI_VERSION >= 20602 /* 2.6.2+ only */
     bool Load(const wxURI& location);
     bool Load(const wxURI& location, const wxURI& proxy);
 
     bool Load(const wxURI& location);
     bool Load(const wxURI& location, const wxURI& proxy);
 
-    wxFileOffset GetDownloadProgress();
-    wxFileOffset GetDownloadTotal();
+    wxFileOffset GetDownloadProgress(); // DirectShow only
+    wxFileOffset GetDownloadTotal();    // DirectShow only
 
     double GetVolume();
     bool   SetVolume(double dVolume);
 
     double GetVolume();
     bool   SetVolume(double dVolume);
@@ -210,7 +217,7 @@ public:
     {   return Load(wxURI(fileName));       }
     bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy)
     {   return Load(wxURI(fileName), wxURI(proxy));       }
     {   return Load(wxURI(fileName));       }
     bool LoadURIWithProxy(const wxString& fileName, const wxString& proxy)
     {   return Load(wxURI(fileName), wxURI(proxy));       }
-
+#endif
 protected:
     static wxClassInfo* NextBackend();
 
 protected:
     static wxClassInfo* NextBackend();
 
@@ -324,12 +331,10 @@ public:
 //Event ID to give to our events
 #define wxMEDIA_FINISHED_ID    13000
 #define wxMEDIA_STOP_ID    13001
 //Event ID to give to our events
 #define wxMEDIA_FINISHED_ID    13000
 #define wxMEDIA_STOP_ID    13001
-#define wxMEDIA_LOADED_ID      13002
 
 //Define our event types - we need to call DEFINE_EVENT_TYPE(EVT) later
 DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_FINISHED, wxMEDIA_FINISHED_ID)
 DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_STOP,     wxMEDIA_STOP_ID)
 
 //Define our event types - we need to call DEFINE_EVENT_TYPE(EVT) later
 DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_FINISHED, wxMEDIA_FINISHED_ID)
 DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_STOP,     wxMEDIA_STOP_ID)
-DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_LOADED,     wxMEDIA_LOADED_ID)
 
 //Function type(s) our events need
 typedef void (wxEvtHandler::*wxMediaEventFunction)(wxMediaEvent&);
 
 //Function type(s) our events need
 typedef void (wxEvtHandler::*wxMediaEventFunction)(wxMediaEvent&);
@@ -340,7 +345,24 @@ typedef void (wxEvtHandler::*wxMediaEventFunction)(wxMediaEvent&);
 //Macro for usage with message maps
 #define EVT_MEDIA_FINISHED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_FINISHED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
 #define EVT_MEDIA_STOP(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_STOP, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
 //Macro for usage with message maps
 #define EVT_MEDIA_FINISHED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_FINISHED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
 #define EVT_MEDIA_STOP(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_STOP, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
-#define EVT_MEDIA_LOADED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_LOADED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
+
+#if wxABI_VERSION >= 20602 /* 2.6.2+ only */
+#   define wxMEDIA_LOADED_ID      13002
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_LOADED,     wxMEDIA_LOADED_ID)
+#   define EVT_MEDIA_LOADED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_LOADED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
+#endif
+
+#if wxABI_VERSION >= 20603 /* 2.6.3+ only */
+#   define wxMEDIA_STATECHANGED_ID      13003
+#   define wxMEDIA_PLAY_ID      13004
+#   define wxMEDIA_PAUSE_ID      13005
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_STATECHANGED,     wxMEDIA_STATECHANGED_ID)
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_PLAY,     wxMEDIA_PLAY_ID)
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_MEDIA_PAUSE,     wxMEDIA_PAUSE_ID)
+#   define EVT_MEDIA_STATECHANGED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_STATECHANGED, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
+#   define EVT_MEDIA_PLAY(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_PLAY, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
+#   define EVT_MEDIA_PAUSE(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_PAUSE, winid, wxID_ANY, wxMediaEventHandler(fn), (wxObject *) NULL ),
+#endif
 
 // ----------------------------------------------------------------------------
 // common backend base class used by many other backends
 
 // ----------------------------------------------------------------------------
 // common backend base class used by many other backends
@@ -353,11 +375,26 @@ public:
     void QueueEvent(wxEventType evtType);
 
     // notify that the movie playback is finished
     void QueueEvent(wxEventType evtType);
 
     // notify that the movie playback is finished
-    void QueueFinishEvent() { QueueEvent(wxEVT_MEDIA_FINISHED); }
+    void QueueFinishEvent()
+    {
+#if wxABI_VERSION >= 20603 /* 2.6.3+ only */
+        QueueEvent(wxEVT_MEDIA_STATECHANGED);
+#endif
+        QueueEvent(wxEVT_MEDIA_FINISHED);
+    }
 
     // send the stop event and return true if it hasn't been vetoed
     bool SendStopEvent();
 
 
     // send the stop event and return true if it hasn't been vetoed
     bool SendStopEvent();
 
+    // Queue pause event
+    void QueuePlayEvent();
+
+    // Queue pause event
+    void QueuePauseEvent();
+
+    // Queue stop event (no veto)
+    void QueueStopEvent();
+
 protected:
     // call this when the movie size has changed but not because it has just
     // been loaded (in this case, call NotifyMovieLoaded() below)
 protected:
     // call this when the movie size has changed but not because it has just
     // been loaded (in this case, call NotifyMovieLoaded() below)
index f2668e6be9e27ced418e8a4a72b1647f7490a488..49bae1ce86ebe09da637ce991ae4b2b508095496 100644 (file)
@@ -1,5 +1,5 @@
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
-// Name:        wx/msw/ole/activex.h
+// Name:        wx/activex.h
 // Purpose:     wxActiveXContainer class
 // Author:      Ryan Norton <wxprojects@comcast.net>
 // Modified by:
 // Purpose:     wxActiveXContainer class
 // Author:      Ryan Norton <wxprojects@comcast.net>
 // Modified by:
@@ -42,6 +42,7 @@
 //  WX includes
 //---------------------------------------------------------------------------
 #include "wx/window.h"
 //  WX includes
 //---------------------------------------------------------------------------
 #include "wx/window.h"
+#include "wx/variant.h"
 
 //---------------------------------------------------------------------------
 // MSW COM includes
 
 //---------------------------------------------------------------------------
 // MSW COM includes
@@ -150,10 +151,6 @@ WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceObject, IOleInPlaceObject)
 WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceActiveObject, IOleInPlaceActiveObject)
 WX_DECLARE_AUTOOLE(wxAutoIOleDocumentView, IOleDocumentView)
 WX_DECLARE_AUTOOLE(wxAutoIViewObject, IViewObject)
 WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceActiveObject, IOleInPlaceActiveObject)
 WX_DECLARE_AUTOOLE(wxAutoIOleDocumentView, IOleDocumentView)
 WX_DECLARE_AUTOOLE(wxAutoIViewObject, IViewObject)
-WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceSite, IOleInPlaceSite)
-WX_DECLARE_AUTOOLE(wxAutoIOleDocument, IOleDocument)
-WX_DECLARE_AUTOOLE(wxAutoIPersistStreamInit, IPersistStreamInit)
-WX_DECLARE_AUTOOLE(wxAutoIAdviseSink, IAdviseSink)
 
 class wxActiveXContainer : public wxWindow
 {
 
 class wxActiveXContainer : public wxWindow
 {
@@ -168,6 +165,7 @@ public:
 
 protected:
     friend class FrameSite;
 
 protected:
     friend class FrameSite;
+    friend class wxActiveXEvents;
 
     wxAutoIDispatch            m_Dispatch;
     wxAutoIOleClientSite      m_clientSite;
 
     wxAutoIDispatch            m_Dispatch;
     wxAutoIOleClientSite      m_clientSite;
@@ -185,4 +183,50 @@ protected:
     void CreateActiveX(REFIID, IUnknown*);
 };
 
     void CreateActiveX(REFIID, IUnknown*);
 };
 
+
+// Events
+class wxActiveXEvent : public wxCommandEvent
+{
+private:
+    friend class wxActiveXEvents;
+    wxVariant m_params;
+    DISPID m_dispid;
+
+public:
+    virtual wxEvent *Clone() const
+    { return new wxActiveXEvent(*this); }
+
+    int ParamCount() const
+    {   return m_params.GetCount();  }
+
+    wxString ParamType(int idx) const
+    {
+        wxASSERT(idx >= 0 && idx < m_params.GetCount());
+        return m_params[idx].GetType();
+    }
+
+    wxString ParamName(int idx) const
+    {
+        wxASSERT(idx >= 0 && idx < m_params.GetCount());
+        return m_params[idx].GetName();
+    }
+
+    wxVariant& operator[] (int idx)
+    {
+        wxASSERT(idx >= 0 && idx < ParamCount());
+        return m_params[idx];
+    }
+
+    DISPID GetDispatchId() const
+    {   return m_dispid;    }
+};
+
+#define wxACTIVEX_ID    14001
+DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_MEDIA, wxEVT_ACTIVEX, wxACTIVEX_ID)
+typedef void (wxEvtHandler::*wxActiveXEventFunction)(wxActiveXEvent&);
+#define EVT_ACTIVEX(id, fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_ACTIVEX, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxActiveXEventFunction) & fn, (wxObject *) NULL ),
+#define wxActiveXEventHandler(func) \
+    (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxActiveXEventFunction, &func)
+
 #endif // _WX_MSW_OLE_ACTIVEXCONTAINER_H_
 #endif // _WX_MSW_OLE_ACTIVEXCONTAINER_H_
+
index 8c9a8475f2f0439e5005e80dc9897580482682ca..7b0e93fc0c8e0f8f2bb4e32027900a058824cebe 100644 (file)
 // 1) Certain backends can't play the same media file at the same time (MCI,
 //    Cocoa NSMovieView-Quicktime).
 // 2) Positioning on Mac Carbon is messed up if put in a sub-control like a
 // 1) Certain backends can't play the same media file at the same time (MCI,
 //    Cocoa NSMovieView-Quicktime).
 // 2) Positioning on Mac Carbon is messed up if put in a sub-control like a
-//    Notebook (like this sample does) on OS versions < 10.2.
-// 3) On unix the video may not work - it only checks for a few video
-//    sinks - xvimagesink, ximagesink and whatever gnome preferences has -
-//    if gnome preferences is not available or you have a different video
-//    sink then those two (such as sdlvideosink) then you'll get black video
+//    Notebook (like this sample does).
 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 // ============================================================================
 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 // ============================================================================
@@ -116,6 +112,8 @@ enum
 //    wxID_EXIT,   [built-in to wxWidgets]
     // Control event IDs
     wxID_SLIDER,
 //    wxID_EXIT,   [built-in to wxWidgets]
     // Control event IDs
     wxID_SLIDER,
+    wxID_PBSLIDER,
+    wxID_VOLSLIDER,
     wxID_NOTEBOOK,
     wxID_MEDIACTRL,
     wxID_BUTTONNEXT,
     wxID_NOTEBOOK,
     wxID_MEDIACTRL,
     wxID_BUTTONNEXT,
@@ -179,9 +177,6 @@ public:
 
     void OnSelectBackend(wxCommandEvent& event);
 
 
     void OnSelectBackend(wxCommandEvent& event);
 
-    // Notebook event handlers
-    void OnPageChange(wxNotebookEvent& event);
-
     // Key event handlers
     void OnKeyDown(wxKeyEvent& event);
 
     // Key event handlers
     void OnKeyDown(wxKeyEvent& event);
 
@@ -198,9 +193,6 @@ public:
     void OnClose(wxCloseEvent& event);
 
 private:
     void OnClose(wxCloseEvent& event);
 
 private:
-    // Rebuild base status string (see Implementation)
-    void ResetStatus();
-
     // Common open file code
     void OpenFile(bool bNewPage);
     void OpenURL(bool bNewPage);
     // Common open file code
     void OpenFile(bool bNewPage);
     void OpenURL(bool bNewPage);
@@ -208,7 +200,6 @@ private:
     void DoPlayFile(const wxString& path);
 
     class wxMediaPlayerTimer* m_timer;     //Timer to write info to status bar
     void DoPlayFile(const wxString& path);
 
     class wxMediaPlayerTimer* m_timer;     //Timer to write info to status bar
-    wxString m_basestatus;      //Base status string (see ResetStatus())
     wxNotebook* m_notebook;     //Notebook containing our pages
 
     // Maybe I should use more accessors, but for simplicity
     wxNotebook* m_notebook;     //Notebook containing our pages
 
     // Maybe I should use more accessors, but for simplicity
@@ -232,8 +223,13 @@ class wxMediaPlayerNotebookPage : public wxPanel
     // Slider event handlers
     void OnBeginSeek(wxScrollEvent& event);
     void OnEndSeek(wxScrollEvent& event);
     // Slider event handlers
     void OnBeginSeek(wxScrollEvent& event);
     void OnEndSeek(wxScrollEvent& event);
+    void OnPBChange(wxScrollEvent& event);
+    void OnVolChange(wxScrollEvent& event);
 
     // Media event handlers
 
     // Media event handlers
+    void OnMediaPlay(wxMediaEvent& event);
+    void OnMediaPause(wxMediaEvent& event);
+    void OnMediaStop(wxMediaEvent& event);
     void OnMediaFinished(wxMediaEvent& event);
 
 public:
     void OnMediaFinished(wxMediaEvent& event);
 
 public:
@@ -248,6 +244,8 @@ public:
     wxMediaCtrl* m_mediactrl;   //Our media control
     class wxMediaPlayerListCtrl* m_playlist;  //Our playlist
     wxSlider* m_slider;         //The slider below our media control
     wxMediaCtrl* m_mediactrl;   //Our media control
     class wxMediaPlayerListCtrl* m_playlist;  //Our playlist
     wxSlider* m_slider;         //The slider below our media control
+    wxSlider* m_pbSlider;       //Lower-left slider for adjusting speed
+    wxSlider* m_volSlider;      //Lower-right slider for adjusting volume
     int m_nLoops;               //Number of times media has looped
     bool m_bLoop;               //Whether we are looping or not
     bool m_bIsBeingDragged;     //Whether the user is dragging the scroll bar
     int m_nLoops;               //Number of times media has looped
     bool m_bLoop;               //Whether we are looping or not
     bool m_bIsBeingDragged;     //Whether the user is dragging the scroll bar
@@ -411,6 +409,9 @@ IMPLEMENT_APP(wxMediaPlayerApp)
 // ----------------------------------------------------------------------------
 bool wxMediaPlayerApp::OnInit()
 {
 // ----------------------------------------------------------------------------
 bool wxMediaPlayerApp::OnInit()
 {
+    // SetAppName() lets wxConfig and others know where to write
+    SetAppName(wxT("wxMediaPlayer"));
+
     wxMediaPlayerFrame *frame =
         new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
     frame->Show(true);
     wxMediaPlayerFrame *frame =
         new wxMediaPlayerFrame(wxT("MediaPlayer wxWidgets Sample"));
     frame->Show(true);
@@ -440,8 +441,8 @@ bool wxMediaPlayerApp::OnInit()
         {
             frame->AddToPlayList((parser.GetParam (paramNr)));
         }
         {
             frame->AddToPlayList((parser.GetParam (paramNr)));
         }
-        wxCommandEvent emptyevt;
-        frame->OnNext(emptyevt);
+        wxCommandEvent theEvent(wxEVT_COMMAND_MENU_SELECTED, wxID_NEXT);
+        frame->AddPendingEvent(theEvent);
     }
 #endif
 
     }
 #endif
 
@@ -660,12 +661,6 @@ wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
     this->Connect(wxID_SELECTBACKEND, wxEVT_COMMAND_MENU_SELECTED,
                   wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend));
 
     this->Connect(wxID_SELECTBACKEND, wxEVT_COMMAND_MENU_SELECTED,
                   wxCommandEventHandler(wxMediaPlayerFrame::OnSelectBackend));
 
-    //
-    // Notebook events
-    //
-    this->Connect(wxID_NOTEBOOK, wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
-                  wxNotebookEventHandler(wxMediaPlayerFrame::OnPageChange));
-
     //
     // Key events
     //
     //
     // Key events
     //
@@ -702,13 +697,13 @@ wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
     //  it properly loads the playlist for each page without
     //  conflicting (loading the same data) with the other ones.
     //
     //  it properly loads the playlist for each page without
     //  conflicting (loading the same data) with the other ones.
     //
-    wxConfigBase* conf = wxConfigBase::Get();
+    wxConfig conf;
     wxString key, outstring;
     for(int i = 0; ; ++i)
     {
         key.clear();
         key << i;
     wxString key, outstring;
     for(int i = 0; ; ++i)
     {
         key.clear();
         key << i;
-        if(!conf->Read(key, &outstring))
+        if(!conf.Read(key, &outstring))
             break;
         page->m_playlist->AddToPlayList(outstring);
     }
             break;
         page->m_playlist->AddToPlayList(outstring);
     }
@@ -717,7 +712,7 @@ wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
     //  Create a timer to update our status bar
     //
     m_timer = new wxMediaPlayerTimer(this);
     //  Create a timer to update our status bar
     //
     m_timer = new wxMediaPlayerTimer(this);
-    m_timer->Start(100);
+    m_timer->Start(500);
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------
@@ -728,6 +723,9 @@ wxMediaPlayerFrame::wxMediaPlayerFrame(const wxString& title)
 // ----------------------------------------------------------------------------
 wxMediaPlayerFrame::~wxMediaPlayerFrame()
 {
 // ----------------------------------------------------------------------------
 wxMediaPlayerFrame::~wxMediaPlayerFrame()
 {
+    //  Shut down our timer
+    delete m_timer;
+
     //
     //  Here we save our info to the registry or whatever
     //  mechanism the OS uses.
     //
     //  Here we save our info to the registry or whatever
     //  mechanism the OS uses.
@@ -751,19 +749,17 @@ wxMediaPlayerFrame::~wxMediaPlayerFrame()
     wxMediaPlayerListCtrl* playlist =
         ((wxMediaPlayerNotebookPage*)m_notebook->GetPage(0))->m_playlist;
 
     wxMediaPlayerListCtrl* playlist =
         ((wxMediaPlayerNotebookPage*)m_notebook->GetPage(0))->m_playlist;
 
-    wxConfigBase* conf = wxConfigBase::Get();
-    conf->DeleteAll();
+    wxConfig conf;
+    conf.DeleteAll();
 
     for(int i = 0; i < playlist->GetItemCount(); ++i)
     {
         wxString* pData = (wxString*) playlist->GetItemData(i);
         wxString s;
         s << i;
 
     for(int i = 0; i < playlist->GetItemCount(); ++i)
     {
         wxString* pData = (wxString*) playlist->GetItemData(i);
         wxString s;
         s << i;
-        conf->Write(s, *(pData));
+        conf.Write(s, *(pData));
         delete pData;
     }
         delete pData;
     }
-
-    delete m_timer;
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------
@@ -785,38 +781,6 @@ void wxMediaPlayerFrame::AddToPlayList(const wxString& szString)
     currentpage->m_playlist->AddToPlayList(szString);
 }
 
     currentpage->m_playlist->AddToPlayList(szString);
 }
 
-
-// ----------------------------------------------------------------------------
-// wxMediaPlayerFrame::ResetStatus
-//
-// Here we just make a simple status string with some useful info about
-// the media that we won't change later - such as the length of the media.
-//
-// We then append some other info that changes in wxMediaPlayerTimer::Notify, then
-// set the status bar to this text.
-//
-// In real applications, you'd want to find a better way to do this,
-// such as static text controls (wxStaticText).
-//
-// We display info here in seconds (wxMediaCtrl uses milliseconds - that's why
-// we divide by 1000).
-//
-// We also reset our loop counter here.
-// ----------------------------------------------------------------------------
-void wxMediaPlayerFrame::ResetStatus()
-{
-    wxMediaCtrl* currentMediaCtrl = 
-        ((wxMediaPlayerNotebookPage*)m_notebook->GetCurrentPage())->m_mediactrl;
-
-    m_basestatus = wxString::Format(wxT("Size(x,y):%i,%i ")
-                                    wxT("Length(Seconds):%u Speed:%1.1fx"),
-    currentMediaCtrl->GetBestSize().x,
-    currentMediaCtrl->GetBestSize().y,
-    (unsigned)((currentMediaCtrl->Length() / 1000)),
-    currentMediaCtrl->GetPlaybackRate()
-    );
-}
-
 // ----------------------------------------------------------------------------
 // wxMediaPlayerFrame::OnQuit
 //
 // ----------------------------------------------------------------------------
 // wxMediaPlayerFrame::OnQuit
 //
@@ -838,10 +802,25 @@ void wxMediaPlayerFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
 void wxMediaPlayerFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
 {
     wxString msg;
 void wxMediaPlayerFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
 {
     wxString msg;
-    msg.Printf( wxT("This is a test of wxMediaCtrl.\n")
-                wxT("Welcome to %s"), wxVERSION_STRING);
+    msg.Printf( wxT("This is a test of wxMediaCtrl.\n\n")
+
+                wxT("Intructions:\n")
+
+                wxT("The top slider shows the current the current position, ")
+                wxT("which you can change by dragging and releasing it.\n")
+
+                wxT("The gauge (progress bar) shows the progress in ")
+                wxT("downloading data of the current file - it may always be ")
+                wxT("Empty due to lack of support from the current backend.\n")
 
 
-    wxMessageBox(msg, wxT("About wxMediaCtrl test"), wxOK | wxICON_INFORMATION, this);
+                wxT("The lower-left slider controls the volume and the lower-")
+                wxT("right slider controls the playback rate/speed of the ")
+                wxT("media\n\n")
+
+                wxT("Currently using: %s"), wxVERSION_STRING);
+
+    wxMessageBox(msg, wxT("About wxMediaCtrl test"),
+                 wxOK | wxICON_INFORMATION, this);
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------
@@ -995,17 +974,11 @@ void wxMediaPlayerFrame::DoPlayFile(const wxString& path)
     {
             if( !currentpage->m_mediactrl->Pause() )
                 wxMessageBox(wxT("Couldn't pause movie!"));
     {
             if( !currentpage->m_mediactrl->Pause() )
                 wxMessageBox(wxT("Couldn't pause movie!"));
-            else
-                currentpage->m_playlist->SetItem(
-                    currentpage->m_nLastFileId, 0, wxT("||"));
         }
         else
         {
             if( !currentpage->m_mediactrl->Play() )
                 wxMessageBox(wxT("Couldn't play movie!"));
         }
         else
         {
             if( !currentpage->m_mediactrl->Play() )
                 wxMessageBox(wxT("Couldn't play movie!"));
-            else
-                currentpage->m_playlist->SetItem(
-                    currentpage->m_nLastFileId, 0, wxT(">"));
         }
     }
     else
         }
     }
     else
@@ -1075,18 +1048,9 @@ void wxMediaPlayerFrame::OnMediaLoaded(wxMediaEvent& WXUNUSED(evt))
         currentpage->m_playlist->SetItem(currentpage->m_nLastFileId, 0, wxT(">"));
     }
 
         currentpage->m_playlist->SetItem(currentpage->m_nLastFileId, 0, wxT(">"));
     }
 
-    currentpage->m_playlist->SetItem(currentpage->m_nLastFileId, 
-                                     2, wxString::Format(wxT("%u"),
-                         (unsigned) currentpage->m_mediactrl->Length() / 1000) 
-                                    );
-
-        ResetStatus();
-
-    currentpage->m_slider->SetRange(0,
-                    (int)(currentpage->m_mediactrl->Length() / 1000));
-    currentpage->m_gauge->SetRange((int)(currentpage->m_mediactrl->Length() / 1000));
 }
 
 }
 
+
 // ----------------------------------------------------------------------------
 // wxMediaPlayerFrame::OnSelectBackend
 //
 // ----------------------------------------------------------------------------
 // wxMediaPlayerFrame::OnSelectBackend
 //
@@ -1408,7 +1372,7 @@ void wxMediaPlayerFrame::OnNext(wxCommandEvent& WXUNUSED(event))
 // ----------------------------------------------------------------------------
 // wxMediaPlayerFrame::OnVolumeDown
 //
 // ----------------------------------------------------------------------------
 // wxMediaPlayerFrame::OnVolumeDown
 //
-// Lowers the volume of the media control by 10%
+// Lowers the volume of the media control by 5%
 // ----------------------------------------------------------------------------
 void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent& WXUNUSED(event))
 {
 // ----------------------------------------------------------------------------
 void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent& WXUNUSED(event))
 {
@@ -1416,13 +1380,13 @@ void wxMediaPlayerFrame::OnVolumeDown(wxCommandEvent& WXUNUSED(event))
         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
 
     double dVolume = currentpage->m_mediactrl->GetVolume();
         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
 
     double dVolume = currentpage->m_mediactrl->GetVolume();
-    currentpage->m_mediactrl->SetVolume(dVolume < 0.1 ? 0.0 : dVolume - .1);
+    currentpage->m_mediactrl->SetVolume(dVolume < 0.05 ? 0.0 : dVolume - .05);
 }
 
 // ----------------------------------------------------------------------------
 // wxMediaPlayerFrame::OnVolumeUp
 //
 }
 
 // ----------------------------------------------------------------------------
 // wxMediaPlayerFrame::OnVolumeUp
 //
-// Increases the volume of the media control by 10%
+// Increases the volume of the media control by 5%
 // ----------------------------------------------------------------------------
 void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent& WXUNUSED(event))
 {
 // ----------------------------------------------------------------------------
 void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent& WXUNUSED(event))
 {
@@ -1430,17 +1394,7 @@ void wxMediaPlayerFrame::OnVolumeUp(wxCommandEvent& WXUNUSED(event))
         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
 
     double dVolume = currentpage->m_mediactrl->GetVolume();
         (wxMediaPlayerNotebookPage*) m_notebook->GetCurrentPage();
 
     double dVolume = currentpage->m_mediactrl->GetVolume();
-    currentpage->m_mediactrl->SetVolume(dVolume > 0.9 ? 1.0 : dVolume + .1);
-}
-
-// ----------------------------------------------------------------------------
-// wxMediaPlayerFrame::OnPageChange
-//
-// Called when the user changes the current notebook page shown
-// ----------------------------------------------------------------------------
-void wxMediaPlayerFrame::OnPageChange(wxNotebookEvent& WXUNUSED(event))
-{
-    ResetStatus();
+    currentpage->m_mediactrl->SetVolume(dVolume > 0.95 ? 1.0 : dVolume + .05);
 }
 
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 }
 
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -1452,42 +1406,94 @@ void wxMediaPlayerFrame::OnPageChange(wxNotebookEvent& WXUNUSED(event))
 // ----------------------------------------------------------------------------
 // wxMediaPlayerTimer::Notify
 //
 // ----------------------------------------------------------------------------
 // wxMediaPlayerTimer::Notify
 //
-// 1) Update our slider with the position were are in in the media
-// 2) Update our status bar with the base text from wxMediaPlayerFrame::ResetStatus,
-//    append some non-static (changing) info to it, then set the
-//    status bar text to that result
+// 1) Updates media information on the status bar
+// 2) Sets the max/min length of the slider and guage
+//
+// Note that the reason we continually do this and don't cache it is because
+// some backends such as GStreamer are dynamic change values all the time
+// and often don't have things like duration or video size available
+// until the media is actually being played
 // ----------------------------------------------------------------------------
 void wxMediaPlayerTimer::Notify()
 {
     wxMediaPlayerNotebookPage* currentpage = 
         (wxMediaPlayerNotebookPage*) m_frame->m_notebook->GetCurrentPage();
 // ----------------------------------------------------------------------------
 void wxMediaPlayerTimer::Notify()
 {
     wxMediaPlayerNotebookPage* currentpage = 
         (wxMediaPlayerNotebookPage*) m_frame->m_notebook->GetCurrentPage();
+    wxMediaCtrl* currentMediaCtrl = currentpage->m_mediactrl;
 
     if(currentpage)
     {
 
     if(currentpage)
     {
-        // if the slider is being dragged then update it with the song position
+        // Number of minutes/seconds total
+        wxLongLong llLength = currentpage->m_mediactrl->Length();
+        int nMinutes = (int) (llLength / 60000).GetValue();
+        int nSeconds = (int) ((llLength % 60000)/1000).GetValue();
+
+        // Duration string (i.e. MM:SS)
+        wxString sDuration;
+        sDuration.Printf(wxT("%2i:%02i"), nMinutes, nSeconds);
+
+
+        // Number of minutes/seconds total
+        wxLongLong llTell = currentpage->m_mediactrl->Tell();
+        nMinutes = (int) (llTell / 60000).GetValue();
+        nSeconds = (int) ((llTell % 60000)/1000).GetValue();
+
+        // Position string (i.e. MM:SS)
+        wxString sPosition;
+        sPosition.Printf(wxT("%2i:%02i"), nMinutes, nSeconds);
+
+
+        // Set the third item in the listctrl entry to the duration string
+        if(currentpage->m_nLastFileId >= 0)
+            currentpage->m_playlist->SetItem(
+                    currentpage->m_nLastFileId, 2, sDuration);
+
+        // Setup the slider and gauge min/max values
+        currentpage->m_slider->SetRange(0, (int)(llLength / 1000).GetValue());
+        currentpage->m_gauge->SetRange(100);
+
+
+        // if the slider is not being dragged then update it with the song position
         if(currentpage->IsBeingDragged() == false)
         if(currentpage->IsBeingDragged() == false)
+            currentpage->m_slider->SetValue((long)(llTell / 1000).GetValue());
+
+
+        // Update the gauge with the download progress
+        wxLongLong llDownloadProgress =
+            currentpage->m_mediactrl->GetDownloadProgress();
+        wxLongLong llDownloadTotal =
+            currentpage->m_mediactrl->GetDownloadTotal();
+
+        if(llDownloadTotal.GetValue() != 0)
         {
         {
-            long lPosition = (long)( currentpage->m_mediactrl->Tell() / 1000 );
-            currentpage->m_slider->SetValue(lPosition);
+            currentpage->m_gauge->SetValue(
+                (int) ((llDownloadProgress * 100) / llDownloadTotal).GetValue()
+                                          );
         }
 
         }
 
-        // update guage with value from slider
-        currentpage->m_gauge->SetValue(currentpage->m_slider->GetValue());
+        // GetBestSize holds the original video size
+        wxSize videoSize = currentMediaCtrl->GetBestSize();
+
+        // Now the big part - set the status bar text to
+        // hold various metadata about the media
 #if wxUSE_STATUSBAR
         m_frame->SetStatusText(wxString::Format(
 #if wxUSE_STATUSBAR
         m_frame->SetStatusText(wxString::Format(
-                        wxT("%s Pos:%u State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
-                        m_frame->m_basestatus.c_str(),
-                        currentpage->m_slider->GetValue(),
+                        wxT("Size(x,y):%i,%i ")
+                        wxT("Position:%s/%s Speed:%1.1fx ")
+                        wxT("State:%s Loops:%i D/T:[%i]/[%i] V:%i%%"),
+                        videoSize.x,
+                        videoSize.y,
+                        sPosition.c_str(),
+                        sDuration.c_str(),
+                        currentMediaCtrl->GetPlaybackRate(),
                         wxGetMediaStateText(currentpage->m_mediactrl->GetState()),
                         currentpage->m_nLoops,
                         wxGetMediaStateText(currentpage->m_mediactrl->GetState()),
                         currentpage->m_nLoops,
-                        (int)currentpage->m_mediactrl->GetDownloadProgress(),
-                        (int)currentpage->m_mediactrl->GetDownloadTotal(),
+                        (int)llDownloadProgress.GetValue(),
+                        (int)llDownloadTotal.GetValue(),
                         (int)(currentpage->m_mediactrl->GetVolume() * 100)));
 #endif // wxUSE_STATUSBAR
     }
 }
 
                         (int)(currentpage->m_mediactrl->GetVolume() * 100)));
 #endif // wxUSE_STATUSBAR
     }
 }
 
-
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 //
 // wxMediaPlayerNotebookPage
 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 //
 // wxMediaPlayerNotebookPage
@@ -1510,7 +1516,6 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
                            m_bIsBeingDragged(false),
                            m_parentFrame(parentFrame)
 {
                            m_bIsBeingDragged(false),
                            m_parentFrame(parentFrame)
 {
-
     //
     //  Layout
     //
     //
     //  Layout
     //
@@ -1539,7 +1544,8 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
     bool bOK = m_mediactrl->Create(this, wxID_MEDIACTRL, wxEmptyString,
                                     wxDefaultPosition, wxDefaultSize, 0,
 //you could specify a macrod backend here like
     bool bOK = m_mediactrl->Create(this, wxID_MEDIACTRL, wxEmptyString,
                                     wxDefaultPosition, wxDefaultSize, 0,
 //you could specify a macrod backend here like
-//wxMEDIABACKEND_QUICKTIME);
+//  wxMEDIABACKEND_WMP10);
+//        wxT("wxPDFMediaBackend"));
                                    szBackend);
 //you could change the cursor here like
 //    m_mediactrl->SetCursor(wxCURSOR_BLANK);
                                    szBackend);
 //you could change the cursor here like
 //    m_mediactrl->SetCursor(wxCURSOR_BLANK);
@@ -1571,8 +1577,8 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
     //  > - Currently Playing
     //  [] - Stopped
     //  || - Paused
     //  > - Currently Playing
     //  [] - Stopped
     //  || - Paused
-    //  (( - Volume Down 10%
-    //  )) - Volume Up 10%
+    //  (( - Volume Down 5%
+    //  )) - Volume Up 5%
     //
     //  Column two is the name of the file
     //
     //
     //  Column two is the name of the file
     //
@@ -1615,7 +1621,7 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
     vertsizer->Add(m_vdButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
     vertsizer->Add(m_vuButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
     horsizer1->Add(vertsizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
     vertsizer->Add(m_vdButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
     vertsizer->Add(m_vuButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
     horsizer1->Add(vertsizer, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
-    sizer->Add(horsizer1, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
+    sizer->Add(horsizer1, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
 
 
     //
 
 
     //
@@ -1628,7 +1634,6 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
                             wxSL_HORIZONTAL );
     sizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
 
                             wxSL_HORIZONTAL );
     sizer->Add(m_slider, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
 
-
     //
     //  Create the gauge
     //
     //
     //  Create the gauge
     //
@@ -1637,6 +1642,26 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
                         wxGA_HORIZONTAL | wxGA_SMOOTH);
     sizer->Add(m_gauge, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
 
                         wxGA_HORIZONTAL | wxGA_SMOOTH);
     sizer->Add(m_gauge, 0, wxALIGN_CENTER_HORIZONTAL|wxALL|wxEXPAND , 5);
 
+    //
+    //  Create the speed/volume sliders
+    //
+    wxBoxSizer* horsizer3 = new wxBoxSizer(wxHORIZONTAL);
+
+    m_volSlider = new wxSlider(this, wxID_VOLSLIDER, 100, // init
+                            0, // start
+                            100, // end
+                            wxDefaultPosition, wxSize(250,20),
+                            wxSL_HORIZONTAL );
+    horsizer3->Add(m_volSlider, 1, wxALL, 5);
+
+    m_pbSlider = new wxSlider(this, wxID_PBSLIDER, 4, // init
+                            1, // start
+                            16, // end
+                            wxDefaultPosition, wxSize(250,20),
+                            wxSL_HORIZONTAL );
+    horsizer3->Add(m_pbSlider, 1, wxALL, 5);
+    sizer->Add(horsizer3, 1, wxCENTRE | wxALL, 5);
+
     //
     // ListCtrl events
     //
     //
     // ListCtrl events
     //
@@ -1651,10 +1676,20 @@ wxMediaPlayerNotebookPage::wxMediaPlayerNotebookPage(wxMediaPlayerFrame* parentF
                   wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek));
     this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBRELEASE,
                   wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek));
                   wxScrollEventHandler(wxMediaPlayerNotebookPage::OnBeginSeek));
     this->Connect(wxID_SLIDER, wxEVT_SCROLL_THUMBRELEASE,
                   wxScrollEventHandler(wxMediaPlayerNotebookPage::OnEndSeek));
+    this->Connect(wxID_PBSLIDER, wxEVT_SCROLL_THUMBRELEASE,
+                    wxScrollEventHandler(wxMediaPlayerNotebookPage::OnPBChange));
+    this->Connect(wxID_VOLSLIDER, wxEVT_SCROLL_THUMBRELEASE,
+                    wxScrollEventHandler(wxMediaPlayerNotebookPage::OnVolChange));
 
     //
     // Media Control events
     //
 
     //
     // Media Control events
     //
+    this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_PLAY,
+                  wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPlay));
+    this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_PAUSE,
+                  wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaPause));
+    this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_STOP,
+                  wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaStop));
     this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED,
                   wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished));
     this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_LOADED,
     this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_FINISHED,
                   wxMediaEventHandler(wxMediaPlayerNotebookPage::OnMediaFinished));
     this->Connect(wxID_MEDIACTRL, wxEVT_MEDIA_LOADED,
@@ -1724,9 +1759,67 @@ bool wxMediaPlayerNotebookPage::IsBeingDragged()
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------
-// OnMediaFinished
+// wxMediaPlayerNotebookPage::OnVolChange
+//
+// Called when the user is done dragging the volume-changing slider
+// ----------------------------------------------------------------------------
+void wxMediaPlayerNotebookPage::OnVolChange(wxScrollEvent& WXUNUSED(event))
+{
+    if( m_mediactrl->SetVolume(
+            m_volSlider->GetValue() / 100.0
+                                   ) == false )
+        wxMessageBox(wxT("Couldn't set volume!"));
+
+}
+
+// ----------------------------------------------------------------------------
+// wxMediaPlayerNotebookPage::OnPBChange
+//
+// Called when the user is done dragging the speed-changing slider
+// ----------------------------------------------------------------------------
+void wxMediaPlayerNotebookPage::OnPBChange(wxScrollEvent& WXUNUSED(event))
+{
+    if( m_mediactrl->SetPlaybackRate(
+            m_pbSlider->GetValue() * .25
+                                   ) == false )
+        wxMessageBox(wxT("Couldn't set playbackrate!"));
+
+}
+
+// ----------------------------------------------------------------------------
+// wxMediaPlayerNotebookPage::OnMediaPlay
+//
+// Called when the media plays.
+// ----------------------------------------------------------------------------
+void wxMediaPlayerNotebookPage::OnMediaPlay(wxMediaEvent& WXUNUSED(event))
+{
+    m_playlist->SetItem(m_nLastFileId, 0, wxT(">"));
+}
+
+// ----------------------------------------------------------------------------
+// wxMediaPlayerNotebookPage::OnMediaPause
+//
+// Called when the media is paused.
+// ----------------------------------------------------------------------------
+void wxMediaPlayerNotebookPage::OnMediaPause(wxMediaEvent& WXUNUSED(event))
+{
+    m_playlist->SetItem(m_nLastFileId, 0, wxT("||"));
+}
+
+// ----------------------------------------------------------------------------
+// wxMediaPlayerNotebookPage::OnMediaStop
+//
+// Called when the media stops.
+// ----------------------------------------------------------------------------
+void wxMediaPlayerNotebookPage::OnMediaStop(wxMediaEvent& WXUNUSED(event))
+{
+    m_playlist->SetItem(m_nLastFileId, 0, wxT("[]"));
+}
+
+// ----------------------------------------------------------------------------
+// wxMediaPlayerNotebookPage::OnMediaFinished
 //
 //
-// Called when the media stops playing.
+// Called when the media finishes playing.
 // Here we loop it if the user wants to (has been selected from file menu)
 // ----------------------------------------------------------------------------
 void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event))
 // Here we loop it if the user wants to (has been selected from file menu)
 // ----------------------------------------------------------------------------
 void wxMediaPlayerNotebookPage::OnMediaFinished(wxMediaEvent& WXUNUSED(event))
index 618eccabf903def604a6168d36e920ea5e1b0224..4cb5a2b8df91771214afb7bdcd0cd6d5e23b84a0 100644 (file)
@@ -9,6 +9,8 @@
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
+// TODO: Platform specific backend defaults?
+
 //===========================================================================
 // Definitions
 //===========================================================================
 //===========================================================================
 // Definitions
 //===========================================================================
 // Pre-compiled header stuff
 //---------------------------------------------------------------------------
 
 // Pre-compiled header stuff
 //---------------------------------------------------------------------------
 
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
+#pragma implementation "mediactrl.h"
+#endif
+
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 // RTTI and Event implementations
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 // RTTI and Event implementations
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
-IMPLEMENT_CLASS(wxMediaCtrl, wxControl)
-IMPLEMENT_CLASS(wxMediaBackend, wxObject)
-IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent)
-DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED)
-DEFINE_EVENT_TYPE(wxEVT_MEDIA_LOADED)
-DEFINE_EVENT_TYPE(wxEVT_MEDIA_STOP)
+IMPLEMENT_CLASS(wxMediaCtrl, wxControl);
+DEFINE_EVENT_TYPE(wxEVT_MEDIA_STATECHANGED)
+DEFINE_EVENT_TYPE(wxEVT_MEDIA_PLAY)
+DEFINE_EVENT_TYPE(wxEVT_MEDIA_PAUSE)
+IMPLEMENT_CLASS(wxMediaBackend, wxObject);
+IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent);
+DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED);
+DEFINE_EVENT_TYPE(wxEVT_MEDIA_LOADED);
+DEFINE_EVENT_TYPE(wxEVT_MEDIA_STOP);
 
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 //
 
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 //
@@ -228,7 +237,7 @@ bool wxMediaCtrl::DoCreate(wxClassInfo* classInfo,
 }
 
 //---------------------------------------------------------------------------
 }
 
 //---------------------------------------------------------------------------
-// wxMediaCtrl::NextBackend
+// wxMediaCtrl::NextBackend (static)
 //
 //
 // Search through the RTTI hashmap one at a
 //
 //
 // Search through the RTTI hashmap one at a
@@ -239,8 +248,7 @@ bool wxMediaCtrl::DoCreate(wxClassInfo* classInfo,
 // STL isn't compatible with and will have a compilation error
 // on a wxNode, however, wxHashTable::compatibility_iterator is
 // incompatible with the old 2.4 stable version - but since
 // STL isn't compatible with and will have a compilation error
 // on a wxNode, however, wxHashTable::compatibility_iterator is
 // incompatible with the old 2.4 stable version - but since
-// we're in 2.5 only we don't need to worry about this
-// static
+// we're in 2.5+ only we don't need to worry about the new version
 //---------------------------------------------------------------------------
 wxClassInfo* wxMediaCtrl::NextBackend()
 {
 //---------------------------------------------------------------------------
 wxClassInfo* wxMediaCtrl::NextBackend()
 {
@@ -507,9 +515,37 @@ void wxMediaBackendCommonBase::QueueEvent(wxEventType evtType)
     m_ctrl->AddPendingEvent(theEvent);
 }
 
     m_ctrl->AddPendingEvent(theEvent);
 }
 
+void wxMediaBackendCommonBase::QueuePlayEvent()
+{
+    QueueEvent(wxEVT_MEDIA_STATECHANGED);
+    QueueEvent(wxEVT_MEDIA_PLAY);
+}
+
+void wxMediaBackendCommonBase::QueuePauseEvent()
+{
+    QueueEvent(wxEVT_MEDIA_STATECHANGED);
+    QueueEvent(wxEVT_MEDIA_PAUSE);
+}
+
+void wxMediaBackendCommonBase::QueueStopEvent()
+{
+    QueueEvent(wxEVT_MEDIA_STATECHANGED);
+    QueueEvent(wxEVT_MEDIA_STOP);
+}
+
+
+//
+// Force link default backends in -
+// see http://wiki.wxwidgets.org/wiki.pl?RTTI
+//
 #include "wx/html/forcelnk.h"
 #include "wx/html/forcelnk.h"
-FORCE_LINK(basewxmediabackends)
 
 
+#ifdef __WXMSW__ // MSW has huge backends so we do it seperately
+FORCE_LINK(wxmediabackend_am);
+FORCE_LINK(wxmediabackend_wmp10);
+#else
+FORCE_LINK(basewxmediabackends);
+#endif
 //---------------------------------------------------------------------------
 // End of compilation guard and of file
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 // End of compilation guard and of file
 //---------------------------------------------------------------------------
index aeb1539217ab19a249dfa99f3274d293f534c51f..e77383dd494218a62ff36ab920728612678847d6 100644 (file)
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 // There are several known bugs with CreateMovieControl
 // on systems > 10.2 - see main.c of QTCarbonShell sample for details
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 // There are several known bugs with CreateMovieControl
 // on systems > 10.2 - see main.c of QTCarbonShell sample for details
+//
+// Also, with either version it will overdraw anything below its TLW - so
+// its relatively useless on a notebook page (this happens in Opera too).
+//
+// Even though though the CreateMovieControl version is the default
+// for OSX, the MovieController version is heavily tested and works
+// just as well...
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
+//===========================================================================
+//  DECLARATIONS
+//===========================================================================
+
+//---------------------------------------------------------------------------
+// Pre-compiled header stuff
+//---------------------------------------------------------------------------
+
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
-#ifdef __BORLANDC__
-#pragma hdrstop
-#endif
-
+//---------------------------------------------------------------------------
+// Includes
+//---------------------------------------------------------------------------
 #include "wx/mediactrl.h"
 
 #include "wx/mediactrl.h"
 
-// uma is for wxMacFSSpec
-#include "wx/mac/uma.h"
-#include "wx/timer.h"
-
-#ifndef __DARWIN__
-#include <Movies.h>
-#include <Gestalt.h>
-#include <QuickTimeComponents.h>    // standard QT stuff
-#else
-#include <QuickTime/QuickTimeComponents.h>
-#endif
-
+//---------------------------------------------------------------------------
+// Compilation guard
+//---------------------------------------------------------------------------
 #if wxUSE_MEDIACTRL
 
 //---------------------------------------------------------------------------
 #if wxUSE_MEDIACTRL
 
 //---------------------------------------------------------------------------
 //===========================================================================
 
 //---------------------------------------------------------------------------
 //===========================================================================
 
 //---------------------------------------------------------------------------
+//
 //  wxQTMediaBackend
 //  wxQTMediaBackend
+//
 //---------------------------------------------------------------------------
 
 //---------------------------------------------------------------------------
 
+//---------------------------------------------------------------------------
+//  QT Includes
+//---------------------------------------------------------------------------
+//uma is for wxMacFSSpec
+#include "wx/mac/uma.h"
+#include "wx/timer.h"
+#ifndef __DARWIN__
+#include <Movies.h>
+#include <Gestalt.h>
+#include <QuickTimeComponents.h>    //Standard QT stuff
+#else
+#include <QuickTime/QuickTimeComponents.h>
+#endif
 
 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
 {
 
 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
 {
@@ -105,43 +125,52 @@ public:
     void FinishLoad();
 
     virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
     void FinishLoad();
 
     virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
+        
+    virtual wxLongLong GetDownloadProgress();
+    virtual wxLongLong GetDownloadTotal();
 
 
+    //
     //  ------  Implementation from now on  --------
     //  ------  Implementation from now on  --------
+    //
+    bool DoPause();
+    bool DoStop();
 
     void DoLoadBestSize();
     void DoSetControllerVisible(wxMediaCtrlPlayerControls flags);
 
 
     void DoLoadBestSize();
     void DoSetControllerVisible(wxMediaCtrlPlayerControls flags);
 
+    wxLongLong GetDataSizeFromStart(TimeValue end);
+
     //TODO: Last param actually long - does this work on 64bit machines?
     //TODO: Last param actually long - does this work on 64bit machines?
-    static Boolean MCFilterProc (MovieController theController,
+    static pascal Boolean MCFilterProc (MovieController theController,
         short action, void *params, long refCon);
 
 #if wxUSE_CREATEMOVIECONTROL
         short action, void *params, long refCon);
 
 #if wxUSE_CREATEMOVIECONTROL
-    void DoCreateMovieControl();
+    void DoCreateMovieControl();    
 #else
     Boolean IsQuickTime4Installed();
     void DoNewMovieController();
 #else
     Boolean IsQuickTime4Installed();
     void DoNewMovieController();
-    static void PPRMProc (Movie theMovie, OSErr theErr, void* theRefCon);
+    static pascal void PPRMProc (Movie theMovie,
+                                 OSErr theErr, void* theRefCon);
 #endif
 
     wxSize m_bestSize;          // Original movie size
 #endif
 
     wxSize m_bestSize;          // Original movie size
-
 #ifdef __WXMAC_OSX__
     struct MovieType** m_movie; // QT Movie handle/instance
 #else
     Movie m_movie;              // Movie instance
 #endif
 #ifdef __WXMAC_OSX__
     struct MovieType** m_movie; // QT Movie handle/instance
 #else
     Movie m_movie;              // Movie instance
 #endif
-
     bool m_bPlaying;            // Whether media is playing or not
     class wxTimer* m_timer;     // Timer for streaming the movie
     MovieController m_mc;       // MovieController instance
     wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags
     bool m_bPlaying;            // Whether media is playing or not
     class wxTimer* m_timer;     // Timer for streaming the movie
     MovieController m_mc;       // MovieController instance
     wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags
-
 #if !wxUSE_CREATEMOVIECONTROL
     EventHandlerRef m_pEventHandlerRef; // Event handler to cleanup
 #if !wxUSE_CREATEMOVIECONTROL
     EventHandlerRef m_pEventHandlerRef; // Event handler to cleanup
+    MoviePrePrerollCompleteUPP  m_preprerollupp;
+    EventHandlerUPP             m_eventupp;
+    MCActionFilterWithRefConUPP m_mcactionupp;
 
     friend class wxQTMediaEvtHandler;
 
     friend class wxQTMediaEvtHandler;
-#endif
-
+#endif    
     DECLARE_DYNAMIC_CLASS(wxQTMediaBackend)
 };
 
     DECLARE_DYNAMIC_CLASS(wxQTMediaBackend)
 };
 
@@ -154,8 +183,7 @@ public:
     {
         m_qtb = qtb;
 
     {
         m_qtb = qtb;
 
-        qtb->m_ctrl->Connect(
-            qtb->m_ctrl->GetId(), wxEVT_ERASE_BACKGROUND,
+        qtb->m_ctrl->Connect(qtb->m_ctrl->GetId(), wxEVT_ERASE_BACKGROUND,
             wxEraseEventHandler(wxQTMediaEvtHandler::OnEraseBackground),
             NULL, this);
     }
             wxEraseEventHandler(wxQTMediaEvtHandler::OnEraseBackground),
             NULL, this);
     }
@@ -170,9 +198,8 @@ private:
 
 // Window event handler
 static pascal OSStatus wxQTMediaWindowEventHandler(
 
 // Window event handler
 static pascal OSStatus wxQTMediaWindowEventHandler(
-    EventHandlerCallRef inHandlerCallRef,
-    EventRef inEvent, void *inUserData);
-DEFINE_ONE_SHOT_HANDLER_GETTER( wxQTMediaWindowEventHandler );
+                                    EventHandlerCallRef inHandlerCallRef, 
+                                    EventRef inEvent, void *inUserData);
 
 #endif
 
 
 #endif
 
@@ -182,7 +209,9 @@ DEFINE_ONE_SHOT_HANDLER_GETTER( wxQTMediaWindowEventHandler );
 
 
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
 // wxQTMediaBackend
 // wxQTMediaBackend
+//
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend)
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend)
@@ -208,25 +237,24 @@ public:
 
     void Notify()
     {
 
     void Notify()
     {
-        // Note that the CreateMovieControl variety performs
-        // its own custom idleing
+        //Note that the CreateMovieControl variety performs
+        //its own custom idleing
 #if !wxUSE_CREATEMOVIECONTROL
         ::MCIdle(m_parent->m_mc);
 #endif
 #if !wxUSE_CREATEMOVIECONTROL
         ::MCIdle(m_parent->m_mc);
 #endif
-
-        // kMovieLoadStatePlayable is not enough on MAC:
-        // it plays, but IsMovieDone might return true (!)
-        // sure we need to wait until kMovieLoadStatePlaythroughOK
-        if (::GetMovieLoadState(m_movie) >= 20000)
-        {
+        //kMovieLoadStatePlayable is not enough on MAC
+        //- it plays, but IsMovieDone might return true (!)
+        //sure we need to wait until kMovieLoadStatePlaythroughOK
+        if(::GetMovieLoadState(m_movie) >= 20000)
+    {
             m_parent->FinishLoad();
             delete this;
             m_parent->FinishLoad();
             delete this;
-        }
+    }
     }
 
 protected:
     }
 
 protected:
-    Movie m_movie;                  // Our movie instance
-    wxQTMediaBackend *m_parent;     // Backend pointer
+    Movie m_movie;                  //Our movie instance
+    wxQTMediaBackend* m_parent;     //Backend pointer
 };
 
 // --------------------------------------------------------------------------
 };
 
 // --------------------------------------------------------------------------
@@ -244,7 +272,7 @@ public:
         m_movie(movie), m_parent(parent) {}
 
     void Notify()
         m_movie(movie), m_parent(parent) {}
 
     void Notify()
-    {
+        {
         //Note that CreateMovieControl performs its own idleing
 #if !wxUSE_CREATEMOVIECONTROL
         //
         //Note that CreateMovieControl performs its own idleing
 #if !wxUSE_CREATEMOVIECONTROL
         //
@@ -262,10 +290,12 @@ public:
         ::MCIdle(m_parent->m_mc);
 #endif
 
         ::MCIdle(m_parent->m_mc);
 #endif
 
+        //
         //  Handle the stop event - if the movie has reached
         //  the end, notify our handler
         //  Handle the stop event - if the movie has reached
         //  the end, notify our handler
-        if (::IsMovieDone(m_movie))
-        {
+        //
+        if(::IsMovieDone(m_movie))
+                {
             if ( m_parent->SendStopEvent() )
             {
                     m_parent->Stop();
             if ( m_parent->SendStopEvent() )
             {
                     m_parent->Stop();
@@ -277,8 +307,8 @@ public:
     }
 
 protected:
     }
 
 protected:
-    Movie m_movie;                  // Our movie instance
-    wxQTMediaBackend* m_parent;     // Backend pointer
+    Movie m_movie;                  //Our movie instance
+    wxQTMediaBackend* m_parent;     //Backend pointer
 };
 
 
 };
 
 
@@ -287,9 +317,12 @@ protected:
 //
 // Sets m_timer to NULL signifying we havn't loaded anything yet
 //---------------------------------------------------------------------------
 //
 // Sets m_timer to NULL signifying we havn't loaded anything yet
 //---------------------------------------------------------------------------
-wxQTMediaBackend::wxQTMediaBackend()
+wxQTMediaBackend::wxQTMediaBackend() 
     : m_movie(NULL), m_bPlaying(false), m_timer(NULL)
       , m_mc(NULL), m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE)
     : m_movie(NULL), m_bPlaying(false), m_timer(NULL)
       , m_mc(NULL), m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE)
+#if !wxUSE_CREATEMOVIECONTROL
+      , m_preprerollupp(NULL)
+#endif
 {
 }
 
 {
 }
 
@@ -304,21 +337,25 @@ wxQTMediaBackend::wxQTMediaBackend()
 //---------------------------------------------------------------------------
 wxQTMediaBackend::~wxQTMediaBackend()
 {
 //---------------------------------------------------------------------------
 wxQTMediaBackend::~wxQTMediaBackend()
 {
-    if (m_movie)
+    if(m_movie)
         Cleanup();
 
 #if !wxUSE_CREATEMOVIECONTROL
     // Cleanup for moviecontroller
         Cleanup();
 
 #if !wxUSE_CREATEMOVIECONTROL
     // Cleanup for moviecontroller
-    if (m_mc)
+    if(m_mc)
     {
         // destroy wxQTMediaEvtHandler we pushed on it
         m_ctrl->PopEventHandler(true);
         RemoveEventHandler((EventHandlerRef&)m_pEventHandlerRef);
     {
         // destroy wxQTMediaEvtHandler we pushed on it
         m_ctrl->PopEventHandler(true);
         RemoveEventHandler((EventHandlerRef&)m_pEventHandlerRef);
+        DisposeEventHandlerUPP(m_eventupp);
+
+        // Dispose of the movie controller
         ::DisposeMovieController(m_mc);
         ::DisposeMovieController(m_mc);
+        DisposeMCActionFilterWithRefConUPP(m_mcactionupp);
     }
 #endif
 
     }
 #endif
 
-    // Note that ExitMovies() is not necessary...
+    //Note that ExitMovies() is not necessary...
     ExitMovies();
 }
 
     ExitMovies();
 }
 
@@ -328,17 +365,15 @@ wxQTMediaBackend::~wxQTMediaBackend()
 // 1) Intializes QuickTime
 // 2) Creates the control window
 //---------------------------------------------------------------------------
 // 1) Intializes QuickTime
 // 2) Creates the control window
 //---------------------------------------------------------------------------
-bool wxQTMediaBackend::CreateControl(
-    wxControl* ctrl,
-    wxWindow* parent,
-    wxWindowID id,
-    const wxPoint& pos,
-    const wxSize& size,
-    long style,
-    const wxValidator& validator,
-    const wxString& name)
+bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
+                                     wxWindowID id,
+                                     const wxPoint& pos,
+                                     const wxSize& size,
+                                     long style,
+                                     const wxValidator& validator,
+                                     const wxString& name)
 {
 {
-    // Don't bother in Native control mode
+    //Don't bother in Native control mode
 #if !wxUSE_CREATEMOVIECONTROL
     if (!IsQuickTime4Installed())
         return false;
 #if !wxUSE_CREATEMOVIECONTROL
     if (!IsQuickTime4Installed())
         return false;
@@ -346,18 +381,19 @@ bool wxQTMediaBackend::CreateControl(
 
     EnterMovies();
 
 
     EnterMovies();
 
+    //
     // Create window
     // By default wxWindow(s) is created with a border -
     // so we need to get rid of those
     //
     // Since we don't have a child window like most other
     // backends, we don't need wxCLIP_CHILDREN
     // Create window
     // By default wxWindow(s) is created with a border -
     // so we need to get rid of those
     //
     // Since we don't have a child window like most other
     // backends, we don't need wxCLIP_CHILDREN
+    //
     if ( !ctrl->wxControl::Create(parent, id, pos, size,
                                  wxWindow::MacRemoveBordersFromStyle(style),
     if ( !ctrl->wxControl::Create(parent, id, pos, size,
                                  wxWindow::MacRemoveBordersFromStyle(style),
-                                  validator, name))
-    {
+                                  validator, name)
+        )
         return false;
         return false;
-    }
 
 #if wxUSE_VALIDATORS
     ctrl->SetValidator(validator);
 
 #if wxUSE_VALIDATORS
     ctrl->SetValidator(validator);
@@ -370,16 +406,16 @@ bool wxQTMediaBackend::CreateControl(
 //---------------------------------------------------------------------------
 // wxQTMediaBackend::IsQuickTime4Installed
 //
 //---------------------------------------------------------------------------
 // wxQTMediaBackend::IsQuickTime4Installed
 //
-// Determines whether version 4 of QT is installed
+// Determines whether version 4 of QT is installed 
 // (Pretty much for classic only)
 //---------------------------------------------------------------------------
 #if !wxUSE_CREATEMOVIECONTROL
 Boolean wxQTMediaBackend::IsQuickTime4Installed()
 {
 // (Pretty much for classic only)
 //---------------------------------------------------------------------------
 #if !wxUSE_CREATEMOVIECONTROL
 Boolean wxQTMediaBackend::IsQuickTime4Installed()
 {
-    OSErr error;
+    short error;
     long result;
 
     long result;
 
-    error = Gestalt(gestaltQuickTime, &result);
+    error = Gestalt (gestaltQuickTime, &result);
     return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0400);
 }
 #endif
     return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0400);
 }
 #endif
@@ -395,42 +431,40 @@ Boolean wxQTMediaBackend::IsQuickTime4Installed()
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Load(const wxString& fileName)
 {
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Load(const wxString& fileName)
 {
-    if (m_movie)
+    if(m_movie)
         Cleanup();
 
     OSErr err = noErr;
     short movieResFile;
     FSSpec sfFile;
 
         Cleanup();
 
     OSErr err = noErr;
     short movieResFile;
     FSSpec sfFile;
 
-    // FIXME:wxMacFilename2FSSpec crashes on empty string -
-    // does it crash on other strings too and should this
-    // "fix" be put in the carbon wxSound?
+    //FIXME:wxMacFilename2FSSpec crashes on empty string -
+    //does it crash on other strings too and should this
+    //"fix" be put in the carbon wxSound?
     if (fileName.empty())
         return false;
 
     if (fileName.empty())
         return false;
 
-    wxMacFilename2FSSpec( fileName, &sfFile );
+    wxMacFilename2FSSpec( fileName , &sfFile );
 
 
-    if (OpenMovieFile( &sfFile, &movieResFile, fsRdPerm ) != noErr)
+    if (OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
         return false;
 
     short movieResID = 0;
     Str255 movieName;
         return false;
 
     short movieResID = 0;
     Str255 movieName;
-    bool result;
-
-    err = NewMovieFromFile(
-        &m_movie,
-        movieResFile,
-        &movieResID,
-        movieName,
-        newMovieActive,
-        NULL); // wasChanged
-    result = (err == noErr);
-
-    // No ::GetMoviesStickyError() here because it returns -2009
+
+    err = NewMovieFromFile (
+    &m_movie,
+    movieResFile,
+    &movieResID,
+    movieName,
+    newMovieActive,
+    NULL); //wasChanged
+
+    //No ::GetMoviesStickyError() here because it returns -2009 
     // a.k.a. invalid track on valid mpegs
     // a.k.a. invalid track on valid mpegs
-    if (result)
+    if(err == noErr)
     {
     {
-        ::CloseMovieFile(movieResFile);
+        ::CloseMovieFile (movieResFile);
 
         // Create movie controller/control
 #if wxUSE_CREATEMOVIECONTROL
 
         // Create movie controller/control
 #if wxUSE_CREATEMOVIECONTROL
@@ -438,11 +472,13 @@ bool wxQTMediaBackend::Load(const wxString& fileName)
 #else
         DoNewMovieController();
 #endif
 #else
         DoNewMovieController();
 #endif
-
-        FinishLoad();
+    FinishLoad();
+        return true;
+    }
+    else
+    {
+        return false;        
     }
     }
-
-    return result;
 }
 
 //---------------------------------------------------------------------------
 }
 
 //---------------------------------------------------------------------------
@@ -453,7 +489,7 @@ bool wxQTMediaBackend::Load(const wxString& fileName)
 // Anyway we set up the loading timer here to tell us when the movie is done
 //---------------------------------------------------------------------------
 #if !wxUSE_CREATEMOVIECONTROL
 // Anyway we set up the loading timer here to tell us when the movie is done
 //---------------------------------------------------------------------------
 #if !wxUSE_CREATEMOVIECONTROL
-void wxQTMediaBackend::PPRMProc (Movie theMovie,
+pascal void wxQTMediaBackend::PPRMProc (Movie theMovie,
                                  OSErr WXUNUSED_UNLESS_DEBUG(theErr),
                                  void* theRefCon)
 {
                                  OSErr WXUNUSED_UNLESS_DEBUG(theErr),
                                  void* theRefCon)
 {
@@ -484,45 +520,43 @@ void wxQTMediaBackend::PPRMProc (Movie theMovie,
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Load(const wxURI& location)
 {
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Load(const wxURI& location)
 {
-    if (m_movie)
+    if(m_movie)
         Cleanup();
 
     wxString theURI = location.BuildURI();
 
     OSErr err = noErr;
         Cleanup();
 
     wxString theURI = location.BuildURI();
 
     OSErr err = noErr;
-    bool result;
 
 
-    // FIXME: lurking Unicode problem here
     Handle theHandle = ::NewHandleClear(theURI.length() + 1);
     wxASSERT(theHandle);
 
     Handle theHandle = ::NewHandleClear(theURI.length() + 1);
     wxASSERT(theHandle);
 
-    ::BlockMoveData(theURI.mb_str(), *theHandle, theURI.length() + 1);
+    ::BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
 
 
-    // create the movie from the handle that refers to the URI
+    //create the movie from the handle that refers to the URI
     err = ::NewMovieFromDataRef(&m_movie, newMovieActive |
                                                     newMovieAsyncOK
     err = ::NewMovieFromDataRef(&m_movie, newMovieActive |
                                                     newMovieAsyncOK
-                                                    /* | newMovieIdleImportOK*/,
+                                                    /*|newMovieIdleImportOK*/,
                                 NULL, theHandle,
                                 URLDataHandlerSubType);
 
     ::DisposeHandle(theHandle);
 
                                 NULL, theHandle,
                                 URLDataHandlerSubType);
 
     ::DisposeHandle(theHandle);
 
-    result = (err == noErr);
-    if (result)
+    if (err == noErr)
     {
 #if wxUSE_CREATEMOVIECONTROL
     {
 #if wxUSE_CREATEMOVIECONTROL
-        // Movie control resets prerolling, so we must create first
+        // Movie control does its own "(pre)prerolling"
+        // but we still need to buffer the movie for the url
         DoCreateMovieControl();
 
         // Setup timer to catch load event
         m_timer = new wxQTMediaLoadTimer(m_movie, this);
         m_timer->Start(MOVIE_DELAY);
 #else
         DoCreateMovieControl();
 
         // Setup timer to catch load event
         m_timer = new wxQTMediaLoadTimer(m_movie, this);
         m_timer->Start(MOVIE_DELAY);
 #else
-        // Movie controller resets prerolling, so we must create first
+        // Movie controller resets prerolling, so we must create first 
         DoNewMovieController();
         DoNewMovieController();
-
+        
         long timeNow;
         long timeNow;
-        Fixed playRate;
+    Fixed playRate;
 
         timeNow = ::GetMovieTime(m_movie, NULL);
         wxASSERT(::GetMoviesError() == noErr);
 
         timeNow = ::GetMovieTime(m_movie, NULL);
         wxASSERT(::GetMoviesError() == noErr);
@@ -530,6 +564,7 @@ bool wxQTMediaBackend::Load(const wxURI& location)
         playRate = ::GetMoviePreferredRate(m_movie);
         wxASSERT(::GetMoviesError() == noErr);
 
         playRate = ::GetMoviePreferredRate(m_movie);
         wxASSERT(::GetMoviesError() == noErr);
 
+        //
         //  Note that the callback here is optional,
         //  but without it PrePrerollMovie can be buggy
         //  (see Apple ml).  Also, some may wonder
         //  Note that the callback here is optional,
         //  but without it PrePrerollMovie can be buggy
         //  (see Apple ml).  Also, some may wonder
@@ -538,14 +573,19 @@ bool wxQTMediaBackend::Load(const wxURI& location)
         //  require it if you don't use a Movie Controller,
         //  which we don't by default.
         //
         //  require it if you don't use a Movie Controller,
         //  which we don't by default.
         //
-        ::PrePrerollMovie(
-            m_movie, timeNow, playRate,
-            wxQTMediaBackend::PPRMProc,
-            (void*)this);
+        m_preprerollupp =
+             NewMoviePrePrerollCompleteUPP(
+                     wxQTMediaBackend::PPRMProc
+                                           );
+
+        ::PrePrerollMovie(m_movie, timeNow, playRate,
+                              m_preprerollupp,
+                              (void*)this);
 #endif
 #endif
+        return true;
     }
     }
-
-    return result;
+    else
+        return false;
 }
 
 //---------------------------------------------------------------------------
 }
 
 //---------------------------------------------------------------------------
@@ -562,54 +602,56 @@ bool wxQTMediaBackend::Load(const wxURI& location)
 #if wxUSE_CREATEMOVIECONTROL
 void wxQTMediaBackend::DoCreateMovieControl()
 {
 #if wxUSE_CREATEMOVIECONTROL
 void wxQTMediaBackend::DoCreateMovieControl()
 {
-    // Native CreateMovieControl QT control (Thanks to Kevin Olliver's
-    // wxQTMovie for some of this).
-    Rect bounds = wxMacGetBoundsForControl(
-        m_ctrl,
-        m_ctrl->GetPosition(),
-        m_ctrl->GetSize());
-
-    // Dispose of old control for new one
+        //
+        //Native CreateMovieControl QT control (Thanks to Kevin Olliver's
+    // wxQTMovie for how to do some of this).
+        //
+            Rect bounds = wxMacGetBoundsForControl(m_ctrl,
+                                                   m_ctrl->GetPosition(),
+                                                   m_ctrl->GetSize());
+
+        //Dispose of old control for new one
     if (m_ctrl->m_peer && m_ctrl->m_peer->Ok() )
         m_ctrl->m_peer->Dispose();
 
     if (m_ctrl->m_peer && m_ctrl->m_peer->Ok() )
         m_ctrl->m_peer->Dispose();
 
-    // Options:
-    // kMovieControlOptionXXX
-    // HideController - hide the movie controller
-    // LocateTopLeft - movie is pinned to top left rather than centered in the control
-    // EnableEditing - Allows programmatic editing and dragn'drop
-    // HandleEditingHI- Installs event stuff for edit menu - forces EnableEditing also
-    // SetKeysEnabled - Allows keyboard input
-    // ManuallyIdled - app handles movie idling rather than internal timer event loop
-    ::CreateMovieControl(
-        (WindowRef)
-        m_ctrl->MacGetTopLevelWindowRef(), //parent
-        &bounds,                         //control bounds
-        m_movie,                         //movie handle
-        kMovieControlOptionHideController
-            | kMovieControlOptionLocateTopLeft
-            | kMovieControlOptionSetKeysEnabled
-            // | kMovieControlOptionManuallyIdled
-        ,                                // flags
-        m_ctrl->m_peer->GetControlRefAddr() );
-
-    ::EmbedControl(
-        m_ctrl->m_peer->GetControlRef(),
-        (ControlRef)m_ctrl->GetParent()->GetHandle());
-
-    // set up MovieController for the new movie
+        //Options-
+        //kMovieControlOptionXXX
+        //HideController - hide the movie controller
+        //LocateTopLeft - movie is pinned to top left rather than centered in the control
+        //EnableEditing - Allows programmatic editing and dragn'drop
+        //HandleEditingHI- Installs event stuff for edit menu - forces EnableEditing also
+        //SetKeysEnabled - Allows keyboard input
+        //ManuallyIdled - app handles movie idling rather than internal timer event loop
+        ::CreateMovieControl(
+                    (WindowRef)
+                   m_ctrl->MacGetTopLevelWindowRef(), //parent
+                       &bounds,                         //control bounds
+                       m_movie,                         //movie handle
+                       kMovieControlOptionHideController
+                       | kMovieControlOptionLocateTopLeft
+                       | kMovieControlOptionSetKeysEnabled
+                 //  | kMovieControlOptionManuallyIdled
+                       ,                                //flags
+                   m_ctrl->m_peer->GetControlRefAddr() );
+
+    ::EmbedControl(m_ctrl->m_peer->GetControlRef(), 
+                    (ControlRef)m_ctrl->GetParent()->GetHandle());    
+                    
+        //
+    // Setup MovieController for the new movie
+        //
     long dataSize;
 
     long dataSize;
 
-    // Get movie controller from our control
-    ::GetControlData(
-        m_ctrl->m_peer->GetControlRef(), 0,
-        kMovieControlDataMovieController,
-        sizeof(MovieController), (Ptr)&m_mc, &dataSize );
+    //Get movie controller from our control
+    ::GetControlData(   m_ctrl->m_peer->GetControlRef(), 0, 
+                    kMovieControlDataMovieController, 
+                    sizeof(MovieController), (Ptr)&m_mc, &dataSize );
 
     // Setup a callback so we can tell when the user presses
     // play on the player controls
 
     // Setup a callback so we can tell when the user presses
     // play on the player controls
-    ::MCSetActionFilterWithRefCon(m_mc,
-            wxQTMediaBackend::MCFilterProc, (long)this);
+    ::MCSetActionFilterWithRefCon(m_mc, 
+            (MCActionFilterWithRefConUPP)wxQTMediaBackend::MCFilterProc,
+            (long)this);
 }
 #endif
 
 }
 #endif
 
@@ -622,75 +664,80 @@ void wxQTMediaBackend::DoCreateMovieControl()
 #if !wxUSE_CREATEMOVIECONTROL
 void wxQTMediaBackend::DoNewMovieController()
 {
 #if !wxUSE_CREATEMOVIECONTROL
 void wxQTMediaBackend::DoNewMovieController()
 {
-    if (!m_mc)
+    if(!m_mc)
     {
         // Get top level window ref for some mac functions
         WindowRef wrTLW = (WindowRef) m_ctrl->MacGetTopLevelWindowRef();
     {
         // Get top level window ref for some mac functions
         WindowRef wrTLW = (WindowRef) m_ctrl->MacGetTopLevelWindowRef();
-
-        // MovieController not setup yet:
+        
+        // MovieController not setup yet - 
         // so we need to create a new one.
         // so we need to create a new one.
-        // You have to pass a valid movie to
+        // You have to pass a valid movie to 
         // NewMovieController, evidently
         ::SetMovieGWorld(m_movie,
                        (CGrafPtr) GetWindowPort(wrTLW),
                        NULL);
         wxASSERT(::GetMoviesError() == noErr);
 
         // NewMovieController, evidently
         ::SetMovieGWorld(m_movie,
                        (CGrafPtr) GetWindowPort(wrTLW),
                        NULL);
         wxASSERT(::GetMoviesError() == noErr);
 
-        Rect bounds = wxMacGetBoundsForControl(
-            m_ctrl,
-            m_ctrl->GetPosition(),
-            m_ctrl->GetSize());
+        Rect bounds = wxMacGetBoundsForControl(m_ctrl,
+                                           m_ctrl->GetPosition(),
+                                           m_ctrl->GetSize());
 
 
-        m_mc = ::NewMovieController(
-            m_movie, &bounds,
-            mcTopLeftMovie | mcNotVisible /* | mcWithFrame */ );
+        m_mc = ::NewMovieController(m_movie, &bounds, mcTopLeftMovie |
+                                                //mcWithFrame |
+                                                mcNotVisible);
         wxASSERT(::GetMoviesError() == noErr);
         wxASSERT(::GetMoviesError() == noErr);
-
         ::MCDoAction(m_mc, 32, (void*)true); //mcActionSetKeysEnabled
         wxASSERT(::GetMoviesError() == noErr);
 
         // Setup a callback so we can tell when the user presses
         // play on the player controls
         ::MCDoAction(m_mc, 32, (void*)true); //mcActionSetKeysEnabled
         wxASSERT(::GetMoviesError() == noErr);
 
         // Setup a callback so we can tell when the user presses
         // play on the player controls
-        ::MCSetActionFilterWithRefCon(m_mc,
-            wxQTMediaBackend::MCFilterProc, (long)this);
+        m_mcactionupp =
+            NewMCActionFilterWithRefConUPP(
+                wxQTMediaBackend::MCFilterProc
+                                          );
+        ::MCSetActionFilterWithRefCon(m_mc, 
+            m_mcactionupp,
+            (long)this);
         wxASSERT(::GetMoviesError() == noErr);
 
         wxASSERT(::GetMoviesError() == noErr);
 
-        // Part of a suggestion from Greg Hazel to repaint
-        // movie when idle
+        //Part of a suggestion from Greg Hazel to repaint
+        //movie when idle
         m_ctrl->PushEventHandler(new wxQTMediaEvtHandler(this));
         m_ctrl->PushEventHandler(new wxQTMediaEvtHandler(this));
-
+        
         // Event types to catch from the TLW
         // for the moviecontroller
         // Event types to catch from the TLW
         // for the moviecontroller
-        EventTypeSpec theEventTypes[] =
-        {
-            { kEventClassMouse,     kEventMouseDown },
-            { kEventClassMouse,     kEventMouseUp },
-            { kEventClassKeyboard,  kEventRawKeyDown },
-            { kEventClassKeyboard,  kEventRawKeyRepeat },
-            { kEventClassKeyboard,  kEventRawKeyUp },
-            { kEventClassWindow,    kEventWindowUpdate },
-            { kEventClassWindow,    kEventWindowActivated },
-            { kEventClassWindow,    kEventWindowDeactivated }
-        };
-
-        // Catch window messages:
+        EventTypeSpec theEventTypes[] = { 
+                    { kEventClassMouse,     kEventMouseDown },
+                    { kEventClassMouse,     kEventMouseUp },
+                    { kEventClassMouse,     kEventMouseDragged },
+                    { kEventClassKeyboard,  kEventRawKeyDown },
+                    { kEventClassKeyboard,  kEventRawKeyRepeat },
+                    { kEventClassKeyboard,  kEventRawKeyUp },
+                    { kEventClassWindow,    kEventWindowUpdate },
+                    { kEventClassWindow,    kEventWindowActivated },
+                    { kEventClassWindow,    kEventWindowDeactivated } 
+                                        };
+                                        
+        // Catch window messages - 
         // if we do not do this and if the user clicks the play
         // button on the controller, for instance, nothing will happen...
         // if we do not do this and if the user clicks the play
         // button on the controller, for instance, nothing will happen...
-        InstallWindowEventHandler( wrTLW,
-                GetwxQTMediaWindowEventHandlerUPP(),
-                GetEventTypeCount( theEventTypes ), theEventTypes,
+        m_eventupp = NewEventHandlerUPP(
+                                        wxQTMediaWindowEventHandler
+                                                      );
+        InstallWindowEventHandler( wrTLW, 
+                m_eventupp,
+                GetEventTypeCount( theEventTypes ), theEventTypes, 
                 m_mc, (&(EventHandlerRef&)m_pEventHandlerRef) );
     }
     else
     {
                 m_mc, (&(EventHandlerRef&)m_pEventHandlerRef) );
     }
     else
     {
-        // MovieController already created:
+        // MovieController already created - 
         // Just change the movie in it and we're good to go
         Point thePoint;
         thePoint.h = thePoint.v = 0;
         // Just change the movie in it and we're good to go
         Point thePoint;
         thePoint.h = thePoint.v = 0;
-        ::MCSetMovie(m_mc, m_movie,
+        ::MCSetMovie(m_mc, m_movie,  
               (WindowRef)m_ctrl->MacGetTopLevelWindowRef(),
                thePoint);
               (WindowRef)m_ctrl->MacGetTopLevelWindowRef(),
                thePoint);
-
         wxASSERT(::GetMoviesError() == noErr);
     }
 }
         wxASSERT(::GetMoviesError() == noErr);
     }
 }
@@ -702,24 +749,28 @@ void wxQTMediaBackend::DoNewMovieController()
 // Performs operations after a movie ready to play/loaded.
 //---------------------------------------------------------------------------
 void wxQTMediaBackend::FinishLoad()
 // Performs operations after a movie ready to play/loaded.
 //---------------------------------------------------------------------------
 void wxQTMediaBackend::FinishLoad()
-{
+{                    
+    // Dispose of the Preprerollmovieupp if we used it
+#if !wxUSE_CREATEMOVIECONTROL
+    DisposeMoviePrePrerollCompleteUPP(m_preprerollupp);
+#endif
     // get the real size of the movie
     DoLoadBestSize();
 
     // get the real size of the movie
     DoLoadBestSize();
 
-    // show the player controls if the user wants to
-    if (m_interfaceflags)
+    // Show the player controls if the user wants to
+    if(m_interfaceflags)
         DoSetControllerVisible(m_interfaceflags);
 
         DoSetControllerVisible(m_interfaceflags);
 
-    // we want millisecond precision
+    //we want millisecond precision
     ::SetMovieTimeScale(m_movie, 1000);
     wxASSERT(::GetMoviesError() == noErr);
 
     ::SetMovieTimeScale(m_movie, 1000);
     wxASSERT(::GetMoviesError() == noErr);
 
-    // start movie progress timer
+    // Start movie progress timer
     m_timer = new wxQTMediaPlayTimer(m_movie, (wxQTMediaBackend*) this);
     wxASSERT(m_timer);
     m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
 
     m_timer = new wxQTMediaPlayTimer(m_movie, (wxQTMediaBackend*) this);
     wxASSERT(m_timer);
     m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
 
-    // send loaded event & refresh size
+    //send loaded event & refresh size
     NotifyMovieLoaded();
 }
 
     NotifyMovieLoaded();
 }
 
@@ -730,12 +781,12 @@ void wxQTMediaBackend::FinishLoad()
 //---------------------------------------------------------------------------
 void wxQTMediaBackend::DoLoadBestSize()
 {
 //---------------------------------------------------------------------------
 void wxQTMediaBackend::DoLoadBestSize()
 {
-    // get the real size of the movie
+    //get the real size of the movie
     Rect outRect;
     ::GetMovieNaturalBoundsRect (m_movie, &outRect);
     wxASSERT(::GetMoviesError() == noErr);
 
     Rect outRect;
     ::GetMovieNaturalBoundsRect (m_movie, &outRect);
     wxASSERT(::GetMoviesError() == noErr);
 
-    // determine best size
+    //determine best size
     m_bestSize.x = outRect.right - outRect.left;
     m_bestSize.y = outRect.bottom - outRect.top;
 }
     m_bestSize.x = outRect.right - outRect.left;
     m_bestSize.y = outRect.bottom - outRect.top;
 }
@@ -744,20 +795,29 @@ void wxQTMediaBackend::DoLoadBestSize()
 // wxQTMediaBackend::Play
 //
 // Start the QT movie
 // wxQTMediaBackend::Play
 //
 // Start the QT movie
+// (Apple recommends mcActionPrerollAndPlay but that's QT 4.1+)
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Play()
 {
     Fixed fixRate = (Fixed) (wxQTMediaBackend::GetPlaybackRate() * 0x10000);
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Play()
 {
     Fixed fixRate = (Fixed) (wxQTMediaBackend::GetPlaybackRate() * 0x10000);
-    if (!fixRate)
+    if(!fixRate)
         fixRate = ::GetMoviePreferredRate(m_movie);
         fixRate = ::GetMoviePreferredRate(m_movie);
-
+    
     wxASSERT(fixRate != 0);
 
     wxASSERT(fixRate != 0);
 
-    if (!m_bPlaying)
-        ::MCDoAction( m_mc, 8 /* mcActionPlay */, (void*) fixRate);
+    if(!m_bPlaying)
+        ::MCDoAction(   m_mc, 8, // mcActionPlay 
+           (void *) fixRate);
+
+    if(::GetMoviesError() == noErr)
+    {
 
     m_bPlaying = true;
 
     m_bPlaying = true;
-    return ::GetMoviesError() == noErr;
+        QueuePlayEvent();
+        return true;
+    }
+    else
+        return false;
 }
 
 //---------------------------------------------------------------------------
 }
 
 //---------------------------------------------------------------------------
@@ -765,18 +825,29 @@ bool wxQTMediaBackend::Play()
 //
 // Stop the movie
 //---------------------------------------------------------------------------
 //
 // Stop the movie
 //---------------------------------------------------------------------------
-bool wxQTMediaBackend::Pause()
+bool wxQTMediaBackend::DoPause()
 {
 {
-    // Stop the movie A.K.A. ::StopMovie(m_movie);
-    if (m_bPlaying)
+    //Stop the movie A.K.A. ::StopMovie(m_movie);
+    if(m_bPlaying)
     {
     {
-        ::MCDoAction( m_mc, 8 /*mcActionPlay*/, (void*) 0);
+        ::MCDoAction(   m_mc, 8 /*mcActionPlay*/, 
+                        (void *) 0);
         m_bPlaying = false;
         m_bPlaying = false;
-        return ::GetMoviesError() == noErr;
+    return ::GetMoviesError() == noErr;
     }
     }
+    return true; //already paused
+}
 
 
-    // already paused
-    return true;
+bool wxQTMediaBackend::Pause()
+{
+    bool bSuccess = DoPause();
+    if(bSuccess)
+    {
+        this->QueuePauseEvent();
+        return true;
+    }
+    else
+        return false;
 }
 
 //---------------------------------------------------------------------------
 }
 
 //---------------------------------------------------------------------------
@@ -785,15 +856,27 @@ bool wxQTMediaBackend::Pause()
 // 1) Stop the movie
 // 2) Seek to the beginning of the movie
 //---------------------------------------------------------------------------
 // 1) Stop the movie
 // 2) Seek to the beginning of the movie
 //---------------------------------------------------------------------------
-bool wxQTMediaBackend::Stop()
+bool wxQTMediaBackend::DoStop()
 {
 {
-    if (!wxQTMediaBackend::Pause())
+    if(!wxQTMediaBackend::DoPause())
         return false;
 
     ::GoToBeginningOfMovie(m_movie);
     return ::GetMoviesError() == noErr;
 }
 
         return false;
 
     ::GoToBeginningOfMovie(m_movie);
     return ::GetMoviesError() == noErr;
 }
 
+bool wxQTMediaBackend::Stop()
+{
+    bool bSuccess = DoStop();
+    if(bSuccess)
+    {
+        QueueStopEvent();
+        return true;
+    }
+    else
+        return false;
+}
+
 //---------------------------------------------------------------------------
 // wxQTMediaBackend::GetPlaybackRate
 //
 //---------------------------------------------------------------------------
 // wxQTMediaBackend::GetPlaybackRate
 //
@@ -865,10 +948,10 @@ double wxQTMediaBackend::GetVolume()
 {
     short sVolume = ::GetMovieVolume(m_movie);
 
 {
     short sVolume = ::GetMovieVolume(m_movie);
 
-    if (sVolume & (128 << 8)) //negative - no sound
+    if(sVolume & (128 << 8)) //negative - no sound
         return 0.0;
 
         return 0.0;
 
-    return sVolume / 256.0;
+    return sVolume/256.0;
 }
 
 //---------------------------------------------------------------------------
 }
 
 //---------------------------------------------------------------------------
@@ -891,7 +974,7 @@ bool wxQTMediaBackend::SetVolume(double dVolume)
     ::SetMovieVolume(m_movie, (short) (dVolume * 256));
     return true;
 }
     ::SetMovieVolume(m_movie, (short) (dVolume * 256));
     return true;
 }
-
  //---------------------------------------------------------------------------
 // wxQTMediaBackend::GetDuration
 //
  //---------------------------------------------------------------------------
 // wxQTMediaBackend::GetDuration
 //
@@ -911,9 +994,9 @@ wxLongLong wxQTMediaBackend::GetDuration()
 wxMediaState wxQTMediaBackend::GetState()
 {
     // Could use
 wxMediaState wxQTMediaBackend::GetState()
 {
     // Could use
-    // GetMovieActive/IsMovieDone/SetMovieActive
+    // GetMovieActive/IsMovieDone/SetMovieActive 
     // combo if implemented that way
     // combo if implemented that way
-    if (m_bPlaying)
+    if (m_bPlaying == true)
         return wxMEDIASTATE_PLAYING;
     else if ( !m_movie || wxQTMediaBackend::GetPosition() == 0)
         return wxMEDIASTATE_STOPPED;
         return wxMEDIASTATE_PLAYING;
     else if ( !m_movie || wxQTMediaBackend::GetPosition() == 0)
         return wxMEDIASTATE_STOPPED;
@@ -930,21 +1013,23 @@ wxMediaState wxQTMediaBackend::GetState()
 void wxQTMediaBackend::Cleanup()
 {
     m_bPlaying = false;
 void wxQTMediaBackend::Cleanup()
 {
     m_bPlaying = false;
-    if (m_timer)
+    if(m_timer)
     {
     {
-        delete m_timer;
-        m_timer = NULL;
+    delete m_timer;
+    m_timer = NULL;
     }
 
     }
 
-    // Stop the movie:
+    // Stop the movie
     // Apple samples with CreateMovieControl typically
     // install a event handler and do this on the dispose
     // event, but we do it here for simplicity
     // (It might keep playing for several seconds after
     // Apple samples with CreateMovieControl typically
     // install a event handler and do this on the dispose
     // event, but we do it here for simplicity
     // (It might keep playing for several seconds after
-    // control destruction if not)
+    //  control destruction if not)
     wxQTMediaBackend::Pause();
     wxQTMediaBackend::Pause();
-
+    
+    //
     // Dispose of control or remove movie from MovieController
     // Dispose of control or remove movie from MovieController
+    //
 #if wxUSE_CREATEMOVIECONTROL
     if (m_ctrl->m_peer && m_ctrl->m_peer->Ok() )
         m_ctrl->m_peer->Dispose();
 #if wxUSE_CREATEMOVIECONTROL
     if (m_ctrl->m_peer && m_ctrl->m_peer->Ok() )
         m_ctrl->m_peer->Dispose();
@@ -956,7 +1041,6 @@ void wxQTMediaBackend::Cleanup()
 #endif
 
     ::DisposeMovie(m_movie);
 #endif
 
     ::DisposeMovie(m_movie);
-    m_movie = NULL;
 }
 
 //---------------------------------------------------------------------------
 }
 
 //---------------------------------------------------------------------------
@@ -964,30 +1048,26 @@ void wxQTMediaBackend::Cleanup()
 //
 // Callback for when the movie controller recieves a message
 //---------------------------------------------------------------------------
 //
 // Callback for when the movie controller recieves a message
 //---------------------------------------------------------------------------
-Boolean wxQTMediaBackend::MCFilterProc(
-    MovieController WXUNUSED(theController),
-    short action,
-    void * WXUNUSED(params),
-    long refCon)
+pascal Boolean wxQTMediaBackend::MCFilterProc(
+                               MovieController WXUNUSED(theController),
+                               short action,
+                               void * WXUNUSED(params),
+                               long refCon)
 {
 {
-    wxQTMediaBackend* pThis = (wxQTMediaBackend*)refCon;
-
-    switch (action)
+    if(action != 1) //don't process idle events
     {
     {
-    case 1:
-        // don't process idle events
-        break;
-
-    case 8:
-        // play button triggered - MC will set movie to opposite state
-        // of current - playing ? paused : playing
-        pThis->m_bPlaying = !(pThis->m_bPlaying);
-        break;
-
-    default:
-        break;
-    }
+        wxQTMediaBackend* pThis = (wxQTMediaBackend*)refCon;
 
 
+        switch(action)
+        {
+        case 8: //play button triggered - MC will set movie to opposite state
+                //of current - playing ? paused : playing
+            pThis->m_bPlaying = !(pThis->m_bPlaying);
+            break;
+        default:
+            break;
+        }
+    }
     return 0;
 }
 
     return 0;
 }
 
@@ -1004,22 +1084,40 @@ wxSize wxQTMediaBackend::GetVideoSize() const
 //---------------------------------------------------------------------------
 // wxQTMediaBackend::Move
 //
 //---------------------------------------------------------------------------
 // wxQTMediaBackend::Move
 //
-// We need to do this even when using native qt control because
-// CreateMovieControl is broken in this regard...
+// Move the movie controller or movie control
+// (we need to actually move the movie control manually...)
+// Top 10 things to do with quicktime in March 93's issue
+// of DEVELOP - very useful
+// http:// www.mactech.com/articles/develop/issue_13/031-033_QuickTime_column.html
+// OLD NOTE: Calling MCSetControllerBoundsRect without detaching
+//          supposively resulted in a crash back then. Current code even
+//          with CFM classic runs fine. If there is ever a problem,
+//          take out the if 0 lines below
 //---------------------------------------------------------------------------
 void wxQTMediaBackend::Move(int x, int y, int w, int h)
 {
 #if !wxUSE_CREATEMOVIECONTROL
 //---------------------------------------------------------------------------
 void wxQTMediaBackend::Move(int x, int y, int w, int h)
 {
 #if !wxUSE_CREATEMOVIECONTROL
-    if (m_timer)
+    if(m_timer)
     {
     {
-        m_ctrl->GetParent()->MacWindowToRootWindow(&x, &y);
+            m_ctrl->GetParent()->MacWindowToRootWindow(&x, &y);
         Rect theRect = {y, x, y+h, x+w};
         Rect theRect = {y, x, y+h, x+w};
-
+#if 0 // see note above
+        ::MCSetControllerAttached(m_mc, FALSE);
+            wxASSERT(::GetMoviesError() == noErr);
+#endif
         ::MCSetControllerBoundsRect(m_mc, &theRect);
         wxASSERT(::GetMoviesError() == noErr);
         ::MCSetControllerBoundsRect(m_mc, &theRect);
         wxASSERT(::GetMoviesError() == noErr);
+
+#if 0 // see note above
+        if(m_interfaceflags)
+        {
+            ::MCSetVisible(m_mc, TRUE);
+                wxASSERT(::GetMoviesError() == noErr);
+    }
+#endif
     }
 #else
     }
 #else
-    if (m_timer && m_ctrl)
+    if(m_timer && m_ctrl)
     {
         m_ctrl->GetParent()->MacWindowToRootWindow(&x, &y);
 
     {
         m_ctrl->GetParent()->MacWindowToRootWindow(&x, &y);
 
@@ -1037,32 +1135,35 @@ void wxQTMediaBackend::Move(int x, int y, int w, int h)
 // and showing/hiding the particular controls on it
 //---------------------------------------------------------------------------
 void wxQTMediaBackend::DoSetControllerVisible(wxMediaCtrlPlayerControls flags)
 // and showing/hiding the particular controls on it
 //---------------------------------------------------------------------------
 void wxQTMediaBackend::DoSetControllerVisible(wxMediaCtrlPlayerControls flags)
-{
-    ::MCSetVisible(m_mc, true);
-
+{    
+    ::MCSetVisible(m_mc, TRUE);
+    
+    //
     // Take care of subcontrols
     // Take care of subcontrols
-    if (::GetMoviesError() == noErr)
+    //
+    if(::GetMoviesError() == noErr)
     {
         long mcFlags = 0;
         ::MCDoAction(m_mc, 39/*mcActionGetFlags*/, (void*)&mcFlags);
     {
         long mcFlags = 0;
         ::MCDoAction(m_mc, 39/*mcActionGetFlags*/, (void*)&mcFlags);
-
-        if (::GetMoviesError() == noErr)
-        {
+        
+        if(::GetMoviesError() == noErr)
+        {            
              mcFlags |= (  //(1<<0)/*mcFlagSuppressMovieFrame*/ |
              mcFlags |= (  //(1<<0)/*mcFlagSuppressMovieFrame*/ |
-                     (1 << 3)/*mcFlagsUseWindowPalette*/
+                     (1<<3)/*mcFlagsUseWindowPalette*/
                        | ((flags & wxMEDIACTRLPLAYERCONTROLS_STEP)
                        | ((flags & wxMEDIACTRLPLAYERCONTROLS_STEP)
-                          ? 0 : (1 << 1)/*mcFlagSuppressStepButtons*/)
+                          ? 0 : (1<<1)/*mcFlagSuppressStepButtons*/)
                        | ((flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME)
                        | ((flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME)
-                          ? 0 : (1 << 2)/*mcFlagSuppressSpeakerButton*/)
-         //              | (1 << 4) /*mcFlagDontInvalidate*/ //if we take care of repainting ourselves
+                          ? 0 : (1<<2)/*mcFlagSuppressSpeakerButton*/)
+         //              | (1<<4) /*mcFlagDontInvalidate*/ //if we take care of repainting ourselves
                           );
                           );
-
-            ::MCDoAction(m_mc, 38/*mcActionSetFlags*/, (void*)mcFlags);
+            ::MCDoAction(m_mc, 38/*mcActionSetFlags*/, (void*)mcFlags);   
         }
         }
-    }
-
-    // Adjust height and width of best size for movie controller
-    // if the user wants it shown
+    }    
+    
+    //
+    //Adjust height and width of best size for movie controller
+    //if the user wants it shown
+    //
     m_bestSize.x = m_bestSize.x > wxMCWIDTH ? m_bestSize.x : wxMCWIDTH;
     m_bestSize.y += wxMCHEIGHT;
 }
     m_bestSize.x = m_bestSize.x > wxMCWIDTH ? m_bestSize.x : wxMCWIDTH;
     m_bestSize.y += wxMCHEIGHT;
 }
@@ -1074,36 +1175,85 @@ void wxQTMediaBackend::DoSetControllerVisible(wxMediaCtrlPlayerControls flags)
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
 {
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
 {
-    if (!m_mc)
+    if(!m_mc)
         return false; //no movie controller...
         return false; //no movie controller...
-
+        
     bool bSizeChanged = false;
     bool bSizeChanged = false;
-
-    // if the controller is visible and we want to hide it do so
-    if (m_interfaceflags && !flags)
+    
+    //if the controller is visible and we want to hide it do so
+    if(m_interfaceflags && !flags)
     {
         bSizeChanged = true;
         DoLoadBestSize();
     {
         bSizeChanged = true;
         DoLoadBestSize();
-        ::MCSetVisible(m_mc, false);
+        ::MCSetVisible(m_mc, FALSE);
     }
     }
-    else if (!m_interfaceflags && flags) //show controller if hidden
+    else if(!m_interfaceflags && flags) //show controller if hidden
     {
         bSizeChanged = true;
         DoSetControllerVisible(flags);
     }
     {
         bSizeChanged = true;
         DoSetControllerVisible(flags);
     }
-
-    // readjust parent sizers
-    if (bSizeChanged)
+    
+    //readjust parent sizers
+    if(bSizeChanged)
     {
     {
-        NotifyMovieSizeChanged();
-
+        NotifyMovieSizeChanged();   
+        
         //remember state in case of loading new media
         m_interfaceflags = flags;
         //remember state in case of loading new media
         m_interfaceflags = flags;
+    }        
+    return ::GetMoviesError() == noErr;
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::GetDataSizeFromStart
+//
+// Calls either GetMovieDataSize or GetMovieDataSize64 with a value
+// of 0 for the starting value
+//---------------------------------------------------------------------------
+wxLongLong wxQTMediaBackend::GetDataSizeFromStart(TimeValue end)
+{
+#if 0 // old pre-qt4 way
+    return ::GetMovieDataSize(m_movie, 0, end)
+#else // qt4 way
+    wide llDataSize;
+    ::GetMovieDataSize64(m_movie, 0, end, &llDataSize);
+    return wxLongLong(llDataSize.hi, llDataSize.lo);
+#endif
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::GetDownloadProgress
+//---------------------------------------------------------------------------
+wxLongLong wxQTMediaBackend::GetDownloadProgress()
+{
+#if 0 // hackish and slow
+    Handle hMovie = NewHandle(0);
+    PutMovieIntoHandle(m_movie, hMovie);
+    long lSize = GetHandleSize(hMovie);
+    DisposeHandle(hMovie);
+    return lSize;
+#else
+    TimeValue tv;
+    if(::GetMaxLoadedTimeInMovie(m_movie, &tv) != noErr)
+    {
+        wxLogDebug(wxT("GetMaxLoadedTimeInMovie failed"));
+        return 0;
     }
     }
+    return wxQTMediaBackend::GetDataSizeFromStart(tv);
+#endif
+}
 
 
-    return ::GetMoviesError() == noErr;
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::GetDownloadTotal
+//---------------------------------------------------------------------------
+wxLongLong wxQTMediaBackend::GetDownloadTotal()
+{
+    return wxQTMediaBackend::GetDataSizeFromStart(
+                    ::GetMovieDuration(m_movie)
+                                                );
 }
 
 }
 
+
 //---------------------------------------------------------------------------
 // wxQTMediaBackend::OnEraseBackground
 //
 //---------------------------------------------------------------------------
 // wxQTMediaBackend::OnEraseBackground
 //
@@ -1115,12 +1265,12 @@ void wxQTMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt)
 {
     // Work around Nasty OSX drawing bug -
     // http://lists.apple.com/archives/QuickTime-API/2002/Feb/msg00311.html
 {
     // Work around Nasty OSX drawing bug -
     // http://lists.apple.com/archives/QuickTime-API/2002/Feb/msg00311.html
-    WindowRef wrTLW =
+    WindowRef wrTLW = 
         (WindowRef) m_qtb->m_ctrl->MacGetTopLevelWindowRef();
 
         (WindowRef) m_qtb->m_ctrl->MacGetTopLevelWindowRef();
 
-    RgnHandle region = MCGetControllerBoundsRgn(m_qtb->m_mc);
-    MCInvalidate(m_qtb->m_mc, wrTLW, region);
-    MCIdle(m_qtb->m_mc);
+    RgnHandle region = ::MCGetControllerBoundsRgn(m_qtb->m_mc);
+    ::MCInvalidate(m_qtb->m_mc, wrTLW, region);
+    ::MCIdle(m_qtb->m_mc);
 }
 #endif
 
 }
 #endif
 
@@ -1131,25 +1281,42 @@ void wxQTMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt)
 // messages to our moviecontroller so it can recieve mouse clicks etc.
 //---------------------------------------------------------------------------
 #if !wxUSE_CREATEMOVIECONTROL
 // messages to our moviecontroller so it can recieve mouse clicks etc.
 //---------------------------------------------------------------------------
 #if !wxUSE_CREATEMOVIECONTROL
-OSStatus wxQTMediaWindowEventHandler(
-    EventHandlerCallRef inHandlerCallRef,
-    EventRef inEvent, void *inUserData)
+static pascal OSStatus wxQTMediaWindowEventHandler(
+                                    EventHandlerCallRef inHandlerCallRef,
+                                        EventRef inEvent, void *inUserData)
 {
 {
+    // for the overly paranoid....
+#if 0
+    UInt32 eventClass = GetEventClass( eventRef );
+    UInt32 eventKind = GetEventKind( inEvent );
+
+    if(eventKind != kEventMouseDown &&
+       eventKind != kEventMouseUp &&
+       eventKind != kEventMouseDragged &&
+       eventKind != kEventRawKeyDown &&
+       eventKind != kEventRawKeyRepeat &&
+       eventKind != kEventRawKeyUp &&
+       eventKind != kEventWindowUpdate &&
+       eventKind != kEventWindowActivated &&
+       eventKind != kEventWindowDeactivated                )
+            return eventNotHandledErr;
+#endif
     EventRecord theEvent;
     ConvertEventRefToEventRecord( inEvent, &theEvent );
     OSStatus err;
     EventRecord theEvent;
     ConvertEventRefToEventRecord( inEvent, &theEvent );
     OSStatus err;
-    err = ::MCIsPlayerEvent( (MovieController) inUserData, &theEvent );
 
 
+    err = ::MCIsPlayerEvent( (MovieController) inUserData, &theEvent );
+    
     // pass on to other event handlers if not handled- i.e. wx
     // pass on to other event handlers if not handled- i.e. wx
-    if (err != noErr)
+    if(err)
         return noErr;
     else
         return eventNotHandledErr;
 }
 #endif
 
         return noErr;
     else
         return eventNotHandledErr;
 }
 #endif
 
-// in source file that contains stuff you don't directly use
+//in source file that contains stuff you don't directly use
 #include "wx/html/forcelnk.h"
 FORCE_LINK_ME(basewxmediabackends)
 
 #include "wx/html/forcelnk.h"
 FORCE_LINK_ME(basewxmediabackends)
 
-#endif // wxUSE_MEDIACTRL
+#endif //wxUSE_MEDIACTRL
diff --git a/src/msw/mediactrl_am.cpp b/src/msw/mediactrl_am.cpp
new file mode 100644 (file)
index 0000000..b1529a5
--- /dev/null
@@ -0,0 +1,2269 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        src/msw/mediactrl_am.cpp
+// Purpose:     ActiveMovie/WMP6/PocketPC 2000 Media Backend for Windows
+// Author:      Ryan Norton <wxprojects@comcast.net>
+// Modified by:
+// Created:     01/29/05
+// RCS-ID:      $Id$
+// Copyright:   (c) Ryan Norton
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+// TODO: Actually test the CE IWMP....
+// TODO: Actually test HTTP proxies...
+
+//-----------------Introduction----------------------------------------------
+// This is the media backend for Windows Media Player 6 and ActiveMovie,
+// as well as PocketPC 2000, Windows Media Player Mobile 7 and 8.
+//
+// We use a combination of the WMP 6 IMediaPlayer interface as well as the
+// ActiveMovie interface IActiveMovie that even exists on Windows 3. For
+// mobile systems we switch to IWMP for WMP mobile 7 and 8 and possibly
+// earlier. We just use ifdefs for differentiating between IWMP and
+// IActiveMovie/IMediaPlayer as the IWMP and IMediaPlayer are virtually
+// identical with a few minor exceptions.
+//
+// For supporting HTTP proxies and such we query the media player
+// interface (IActiveMovie/IWMP) for the INSPlay (NetShow) interface.
+//
+// The IMediaPlayer/IActiveMovie/IWMP are rather clean and straightforward
+// interfaces that are fairly simplistic.
+//
+// Docs for IMediaPlayer are at
+// http://msdn.microsoft.com/library/en-us/wmp6sdk/htm/microsoftwindowsmediaplayercontrolversion64sdk.asp
+//
+// Docs for IWMP are at
+// http://msdn.microsoft.com/library/en-us/wcewmp/html/_wcesdk_asx_wmp_control_reference.asp
+
+//===========================================================================
+//  DECLARATIONS
+//===========================================================================
+
+//---------------------------------------------------------------------------
+// Pre-compiled header stuff
+//---------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+// disable "cast truncates constant value" for VARIANT_BOOL values
+// passed as parameters in VC6
+#ifdef _MSC_VER
+#pragma warning (disable:4310)
+#endif
+
+//---------------------------------------------------------------------------
+// MediaCtrl include
+//---------------------------------------------------------------------------
+#include "wx/mediactrl.h"
+
+//---------------------------------------------------------------------------
+// Compilation guard
+//---------------------------------------------------------------------------
+#if wxUSE_MEDIACTRL
+
+//---------------------------------------------------------------------------
+// WX Includes
+//---------------------------------------------------------------------------
+#include "wx/log.h"         // wxLogDebug
+#include "wx/math.h"        // log10 & pow
+#include "wx/msw/private.h" // user info and wndproc setting/getting
+#include "wx/dcclient.h"
+#include "wx/timer.h"
+#include "wx/dynlib.h"
+#include "wx/stopwatch.h"
+
+//---------------------------------------------------------------------------
+//  wxActiveXContainer - includes all the COM-specific stuff we need
+//---------------------------------------------------------------------------
+#include "wx/msw/ole/activex.h"
+
+// It may sound odd, but you can actually compile this with
+// __WXWINCE__ enabled on non-CE windows
+//#define __WXWINCE__
+
+//---------------------------------------------------------------------------
+//  IIDS - used by CoCreateInstance and IUnknown::QueryInterface
+//
+//  [idl name]          [idl decription]
+//  amcompat.idl        Microsoft Active Movie Control (Ver 2.0)
+//  nscompat.idl        Microsoft NetShow Player (Ver 1.0)
+//  msdxm.idl           Windows Media Player (Ver 1.0)
+//  quartz.idl
+//
+//  First, when I say I "from XXX.idl", I mean I go into the COM Browser
+//  ($Microsoft Visual Studio$/Common/Tools/OLEVIEW.EXE), open
+//  "type libraries", open a specific type library (for quartz for example its
+//  "ActiveMovie control type library (V1.0)"), save it as an .idl, compile the
+//  idl using the midl compiler that comes with visual studio
+//  ($Microsoft Visual Studio$/VC98/bin/midl.exe on VC6) with the /h argument
+//  to make it generate stubs (a .h & .c file), then clean up the generated
+//  interfaces I want with the STDMETHOD wrappers and then put them into
+//  mediactrl.cpp.
+//
+//  According to the MSDN docs, IMediaPlayer requires Windows 98 SE
+//  or greater.  NetShow is available on Windows 3.1 and I'm guessing
+//  IActiveMovie is too.  IMediaPlayer is essentially the Windows Media
+//  Player 6.4 SDK.
+//
+//  IWMP is from PlayerOCX.idl on PocketPC 2000, which uses CLSID_MediaPlayer
+//  as well as the main windows line.
+//
+//  Some of these are not used but are kept here for future reference anyway
+//---------------------------------------------------------------------------
+const IID IID_IActiveMovie          = {0x05589FA2,0xC356,0x11CE,{0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A}};
+const IID IID_IActiveMovie2         = {0xB6CD6554,0xE9CB,0x11D0,{0x82,0x1F,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
+const IID IID_IActiveMovie3         = {0x265EC140,0xAE62,0x11D1,{0x85,0x00,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
+
+const IID IID_INSOPlay              = {0x2179C5D1,0xEBFF,0x11CF,{0xB6,0xFD,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
+const IID IID_INSPlay               = {0xE7C4BE80,0x7960,0x11D0,{0xB7,0x27,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
+const IID IID_INSPlay1              = {0x265EC141,0xAE62,0x11D1,{0x85,0x00,0x00,0xA0,0xC9,0x1F,0x9C,0xA0}};
+
+const IID IID_IMediaPlayer          = {0x22D6F311,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
+const IID IID_IMediaPlayer2         = {0x20D4F5E0,0x5475,0x11D2,{0x97,0x74,0x00,0x00,0xF8,0x08,0x55,0xE6}};
+
+
+#ifdef __WXWINCE__
+const IID IID_IWMP                  = {0x136B66EC,0xF30D,0x46A8,{0x88,0xDD,0xF2,0xD0,0x55,0x16,0x3E,0x49}};
+#endif
+
+const CLSID CLSID_ActiveMovie       = {0x05589FA1,0xC356,0x11CE,{0xBF,0x01,0x00,0xAA,0x00,0x55,0x59,0x5A}};
+const CLSID CLSID_MediaPlayer       = {0x22D6F312,0xB0F6,0x11D0,{0x94,0xAB,0x00,0x80,0xC7,0x4C,0x7E,0x95}};
+const CLSID CLSID_NSPlay            = {0x2179C5D3,0xEBFF,0x11CF,{0xB6,0xFD,0x00,0xAA,0x00,0xB4,0xE2,0x20}};
+
+const IID IID_IAMOpenProgress = {0x8E1C39A1, 0xDE53, 0x11CF,{0xAA, 0x63, 0x00, 0x80, 0xC7, 0x44, 0x52, 0x8D}};
+
+// QUARTZ
+const CLSID CLSID_FilgraphManager = {0xE436EBB3,0x524F,0x11CE,{0x9F,0x53,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
+const IID IID_IMediaEvent = {0x56A868B6,0x0AD4,0x11CE,{0xB0,0x3A,0x00,0x20,0xAF,0x0B,0xA7,0x70}};
+
+//??  QUARTZ Also?
+const CLSID CLSID_VideoMixingRenderer9 ={0x51B4ABF3, 0x748F, 0x4E3B,{0xA2, 0x76, 0xC8, 0x28, 0x33, 0x0E, 0x92, 0x6A}};
+const IID IID_IVMRWindowlessControl9 =  {0x8F537D09, 0xF85E, 0x4414,{0xB2, 0x3B, 0x50, 0x2E, 0x54, 0xC7, 0x99, 0x27}};
+const IID IID_IFilterGraph =            {0x56A8689F, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
+const IID IID_IGraphBuilder =           {0x56A868A9, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
+const IID IID_IVMRFilterConfig9 =       {0x5A804648, 0x4F66, 0x4867,{0x9C, 0x43, 0x4F, 0x5C, 0x82, 0x2C, 0xF1, 0xB8}};
+const IID IID_IBaseFilter =             {0x56A86895, 0x0AD4, 0x11CE,{0xB0, 0x3A, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70}};
+
+//---------------------------------------------------------------------------
+//  QUARTZ COM INTERFACES (dumped from quartz.idl from MSVC COM Browser)
+//---------------------------------------------------------------------------
+
+struct IAMOpenProgress : public IUnknown
+{
+    STDMETHOD(QueryProgress)(LONGLONG *pllTotal, LONGLONG *pllCurrent) PURE;
+    STDMETHOD(AbortOperation)(void) PURE;
+};
+
+struct IMediaEvent : public IDispatch
+{
+    STDMETHOD(GetEventHandle)(LONG_PTR *) PURE;
+    STDMETHOD(GetEvent)(long *, LONG_PTR *, LONG_PTR *, long) PURE;
+    STDMETHOD(WaitForCompletion)(long, long *) PURE;
+    STDMETHOD(CancelDefaultHandling)(long) PURE;
+    STDMETHOD(RestoreDefaultHandling)(long) PURE;
+    STDMETHOD(FreeEventParams)(long, LONG_PTR, LONG_PTR) PURE;
+};
+
+//---------------------------------------------------------------------------
+//  ACTIVEMOVIE COM INTERFACES (dumped from amcompat.idl from MSVC COM Browser)
+//---------------------------------------------------------------------------
+
+enum ReadyStateConstants
+{
+    amvUninitialized  = 0,
+    amvLoading        = 1,
+    amvInteractive    = 3,
+    amvComplete       = 4
+};
+
+enum StateConstants
+{
+    amvNotLoaded    = -1,
+    amvStopped      = 0,
+    amvPaused       = 1,
+    amvRunning      = 2
+};
+
+enum DisplayModeConstants
+{
+    amvTime      = 0,
+    amvFrames    = 1
+};
+
+enum WindowSizeConstants
+{
+    amvOriginalSize    = 0,
+    amvDoubleOriginalSize    = 1,
+    amvOneSixteenthScreen    = 2,
+    amvOneFourthScreen    = 3,
+    amvOneHalfScreen    = 4
+};
+
+enum AppearanceConstants
+{
+    amvFlat    = 0,
+    amv3D    = 1
+};
+
+enum BorderStyleConstants
+{
+    amvNone    = 0,
+    amvFixedSingle    = 1
+};
+
+struct IActiveMovie : public IDispatch
+{
+    STDMETHOD(AboutBox)( void) PURE;
+    STDMETHOD(Run)( void) PURE;
+    STDMETHOD(Pause)( void) PURE;
+    STDMETHOD(Stop)( void) PURE;
+    STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
+    STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
+    STDMETHOD(get_Author)(BSTR __RPC_FAR *pbstrAuthor) PURE;
+    STDMETHOD(get_Title)(BSTR __RPC_FAR *pbstrTitle) PURE;
+    STDMETHOD(get_Copyright)(BSTR __RPC_FAR *pbstrCopyright) PURE;
+    STDMETHOD(get_Description)(BSTR __RPC_FAR *pbstrDescription) PURE;
+    STDMETHOD(get_Rating)(BSTR __RPC_FAR *pbstrRating) PURE;
+    STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
+    STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
+    STDMETHOD(get_Duration)(double __RPC_FAR *pValue) PURE;
+    STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pValue) PURE;
+    STDMETHOD(put_CurrentPosition)(double pValue) PURE;
+    STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
+    STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
+    STDMETHOD(get_SelectionStart)(double __RPC_FAR *pValue) PURE;
+    STDMETHOD(put_SelectionStart)(double pValue) PURE;
+    STDMETHOD(get_SelectionEnd)(double __RPC_FAR *pValue) PURE;
+    STDMETHOD(put_SelectionEnd)(double pValue) PURE;
+    STDMETHOD(get_CurrentState)(StateConstants __RPC_FAR *pState) PURE;
+    STDMETHOD(get_Rate)(double __RPC_FAR *pValue) PURE;
+    STDMETHOD(put_Rate)(double pValue) PURE;
+    STDMETHOD(get_Volume)(long __RPC_FAR *pValue) PURE;
+    STDMETHOD(put_Volume)(long pValue) PURE;
+    STDMETHOD(get_Balance)(long __RPC_FAR *pValue) PURE;
+    STDMETHOD(put_Balance)(long pValue) PURE;
+    STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
+    STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnable) PURE;
+    STDMETHOD(get_ShowDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
+    STDMETHOD(put_ShowDisplay)(VARIANT_BOOL Show) PURE;
+    STDMETHOD(get_ShowControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
+    STDMETHOD(put_ShowControls)(VARIANT_BOOL Show) PURE;
+    STDMETHOD(get_ShowPositionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
+    STDMETHOD(put_ShowPositionControls)(VARIANT_BOOL Show) PURE;
+    STDMETHOD(get_ShowSelectionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
+    STDMETHOD(put_ShowSelectionControls)(VARIANT_BOOL Show) PURE;
+    STDMETHOD(get_ShowTracker)(VARIANT_BOOL __RPC_FAR *Show) PURE;
+    STDMETHOD(put_ShowTracker)(VARIANT_BOOL Show) PURE;
+    STDMETHOD(get_EnablePositionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
+    STDMETHOD(put_EnablePositionControls)(VARIANT_BOOL Enable) PURE;
+    STDMETHOD(get_EnableSelectionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
+    STDMETHOD(put_EnableSelectionControls)(VARIANT_BOOL Enable) PURE;
+    STDMETHOD(get_EnableTracker)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
+    STDMETHOD(put_EnableTracker)(VARIANT_BOOL Enable) PURE;
+    STDMETHOD(get_AllowHideDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
+    STDMETHOD(put_AllowHideDisplay)(VARIANT_BOOL Show) PURE;
+    STDMETHOD(get_AllowHideControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
+    STDMETHOD(put_AllowHideControls)(VARIANT_BOOL Show) PURE;
+    STDMETHOD(get_DisplayMode)(DisplayModeConstants __RPC_FAR *pValue) PURE;
+    STDMETHOD(put_DisplayMode)(DisplayModeConstants pValue) PURE;
+    STDMETHOD(get_AllowChangeDisplayMode)(VARIANT_BOOL __RPC_FAR *fAllow) PURE;
+    STDMETHOD(put_AllowChangeDisplayMode)(VARIANT_BOOL fAllow) PURE;
+    STDMETHOD(get_FilterGraph)(IUnknown __RPC_FAR *__RPC_FAR *ppFilterGraph) PURE;
+    STDMETHOD(put_FilterGraph)(IUnknown __RPC_FAR *ppFilterGraph) PURE;
+    STDMETHOD(get_FilterGraphDispatch)(IDispatch __RPC_FAR *__RPC_FAR *pDispatch) PURE;
+    STDMETHOD(get_DisplayForeColor)(unsigned long __RPC_FAR *ForeColor) PURE;
+    STDMETHOD(put_DisplayForeColor)(unsigned long ForeColor) PURE;
+    STDMETHOD(get_DisplayBackColor)(unsigned long __RPC_FAR *BackColor) PURE;
+    STDMETHOD(put_DisplayBackColor)(unsigned long BackColor) PURE;
+    STDMETHOD(get_MovieWindowSize)(WindowSizeConstants __RPC_FAR *WindowSize) PURE;
+    STDMETHOD(put_MovieWindowSize)(WindowSizeConstants WindowSize) PURE;
+    STDMETHOD(get_FullScreenMode)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
+    STDMETHOD(put_FullScreenMode)(VARIANT_BOOL pEnable) PURE;
+    STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
+    STDMETHOD(put_AutoStart)(VARIANT_BOOL pEnable) PURE;
+    STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pEnable) PURE;
+    STDMETHOD(put_AutoRewind)(VARIANT_BOOL pEnable) PURE;
+    STDMETHOD(get_hWnd)(long __RPC_FAR *hWnd) PURE;
+    STDMETHOD(get_Appearance)(AppearanceConstants __RPC_FAR *pAppearance) PURE;
+    STDMETHOD(put_Appearance)(AppearanceConstants pAppearance) PURE;
+    STDMETHOD(get_BorderStyle)(BorderStyleConstants __RPC_FAR *pBorderStyle) PURE;
+    STDMETHOD(put_BorderStyle)(BorderStyleConstants pBorderStyle) PURE;
+    STDMETHOD(get_Enabled)(VARIANT_BOOL __RPC_FAR *pEnabled) PURE;
+    STDMETHOD(put_Enabled)(VARIANT_BOOL pEnabled) PURE;
+    STDMETHOD(get_Info)(long __RPC_FAR *ppInfo) PURE;
+};
+
+
+
+struct IActiveMovie2 : public IActiveMovie
+{
+    STDMETHOD(IsSoundCardEnabled)(VARIANT_BOOL __RPC_FAR *pbSoundCard) PURE;
+    STDMETHOD(get_ReadyState)(ReadyStateConstants __RPC_FAR *pValue) PURE;
+};
+
+struct IActiveMovie3 : public IActiveMovie2
+{
+    STDMETHOD(get_MediaPlayer)(IDispatch __RPC_FAR *__RPC_FAR *ppDispatch) PURE;
+};
+
+
+//---------------------------------------------------------------------------
+//  MEDIAPLAYER COM INTERFACES (dumped from msdxm.idl from MSVC COM Browser)
+//---------------------------------------------------------------------------
+
+enum MPPlayStateConstants
+{
+    mpStopped = 0,
+    mpPaused    = 1,
+    mpPlaying    = 2,
+    mpWaiting    = 3,
+    mpScanForward    = 4,
+    mpScanReverse    = 5,
+    mpClosed    = 6
+};
+
+enum MPDisplaySizeConstants
+{
+    mpDefaultSize = 0,
+    mpHalfSize    = 1,
+    mpDoubleSize    = 2,
+    mpFullScreen    = 3,
+    mpFitToSize    = 4,
+    mpOneSixteenthScreen    = 5,
+    mpOneFourthScreen    = 6,
+    mpOneHalfScreen    = 7
+};
+
+enum MPReadyStateConstants
+{
+    mpReadyStateUninitialized = 0,
+    mpReadyStateLoading    = 1,
+    mpReadyStateInteractive    = 3,
+    mpReadyStateComplete    = 4
+};
+
+typedef unsigned long VB_OLE_COLOR;
+
+enum MPDisplayModeConstants
+{
+    mpTime = 0,
+    mpFrames    = 1
+};
+
+enum MPMoreInfoType
+{
+    mpShowURL = 0,
+    mpClipURL    = 1,
+    mpBannerURL    = 2
+};
+
+enum MPMediaInfoType
+{
+    mpShowFilename = 0,
+    mpShowTitle    = 1,
+    mpShowAuthor    = 2,
+    mpShowCopyright    = 3,
+    mpShowRating    = 4,
+    mpShowDescription    = 5,
+    mpShowLogoIcon    = 6,
+    mpClipFilename    = 7,
+    mpClipTitle    = 8,
+    mpClipAuthor    = 9,
+    mpClipCopyright    = 10,
+    mpClipRating    = 11,
+    mpClipDescription    = 12,
+    mpClipLogoIcon    = 13,
+    mpBannerImage    = 14,
+    mpBannerMoreInfo    = 15,
+    mpWatermark    = 16
+};
+
+enum DVDMenuIDConstants
+{
+    dvdMenu_Title    = 2,
+    dvdMenu_Root    = 3,
+    dvdMenu_Subpicture    = 4,
+    dvdMenu_Audio    = 5,
+    dvdMenu_Angle    = 6,
+    dvdMenu_Chapter    = 7
+};
+
+enum MPShowDialogConstants
+{
+    mpShowDialogHelp = 0,
+    mpShowDialogStatistics    = 1,
+    mpShowDialogOptions    = 2,
+    mpShowDialogContextMenu    = 3
+};
+
+
+struct IMediaPlayer : public IDispatch
+{
+    STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pCurrentPosition) PURE;
+    STDMETHOD(put_CurrentPosition)(double pCurrentPosition) PURE;
+    STDMETHOD(get_Duration)(double __RPC_FAR *pDuration) PURE;
+    STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
+    STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
+    STDMETHOD(get_MarkerCount)(long __RPC_FAR *pMarkerCount) PURE;
+    STDMETHOD(get_CanScan)(VARIANT_BOOL __RPC_FAR *pCanScan) PURE;
+    STDMETHOD(get_CanSeek)(VARIANT_BOOL __RPC_FAR *pCanSeek) PURE;
+    STDMETHOD(get_CanSeekToMarkers)(VARIANT_BOOL __RPC_FAR *pCanSeekToMarkers) PURE;
+    STDMETHOD(get_CurrentMarker)(long __RPC_FAR *pCurrentMarker) PURE;
+    STDMETHOD(put_CurrentMarker)(long pCurrentMarker) PURE;
+    STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
+    STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
+    STDMETHOD(get_SourceLink)(BSTR __RPC_FAR *pbstrSourceLink) PURE;
+    STDMETHOD(get_CreationDate)(DATE __RPC_FAR *pCreationDate) PURE;
+    STDMETHOD(get_ErrorCorrection)(BSTR __RPC_FAR *pbstrErrorCorrection) PURE;
+    STDMETHOD(get_Bandwidth)(long __RPC_FAR *pBandwidth) PURE;
+    STDMETHOD(get_SourceProtocol)(long __RPC_FAR *pSourceProtocol) PURE;
+    STDMETHOD(get_ReceivedPackets)(long __RPC_FAR *pReceivedPackets) PURE;
+    STDMETHOD(get_RecoveredPackets)(long __RPC_FAR *pRecoveredPackets) PURE;
+    STDMETHOD(get_LostPackets)(long __RPC_FAR *pLostPackets) PURE;
+    STDMETHOD(get_ReceptionQuality)(long __RPC_FAR *pReceptionQuality) PURE;
+    STDMETHOD(get_BufferingCount)(long __RPC_FAR *pBufferingCount) PURE;
+    STDMETHOD(get_IsBroadcast)(VARIANT_BOOL __RPC_FAR *pIsBroadcast) PURE;
+    STDMETHOD(get_BufferingProgress)(long __RPC_FAR *pBufferingProgress) PURE;
+    STDMETHOD(get_ChannelName)(BSTR __RPC_FAR *pbstrChannelName) PURE;
+    STDMETHOD(get_ChannelDescription)(BSTR __RPC_FAR *pbstrChannelDescription) PURE;
+    STDMETHOD(get_ChannelURL)(BSTR __RPC_FAR *pbstrChannelURL) PURE;
+    STDMETHOD(get_ContactAddress)(BSTR __RPC_FAR *pbstrContactAddress) PURE;
+    STDMETHOD(get_ContactPhone)(BSTR __RPC_FAR *pbstrContactPhone) PURE;
+    STDMETHOD(get_ContactEmail)(BSTR __RPC_FAR *pbstrContactEmail) PURE;
+    STDMETHOD(get_BufferingTime)(double __RPC_FAR *pBufferingTime) PURE;
+    STDMETHOD(put_BufferingTime)(double pBufferingTime) PURE;
+    STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pAutoStart) PURE;
+    STDMETHOD(put_AutoStart)(VARIANT_BOOL pAutoStart) PURE;
+    STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pAutoRewind) PURE;
+    STDMETHOD(put_AutoRewind)(VARIANT_BOOL pAutoRewind) PURE;
+    STDMETHOD(get_Rate)(double __RPC_FAR *pRate) PURE;
+    STDMETHOD(put_Rate)(double pRate) PURE;
+    STDMETHOD(get_SendKeyboardEvents)(VARIANT_BOOL __RPC_FAR *pSendKeyboardEvents) PURE;
+    STDMETHOD(put_SendKeyboardEvents)(VARIANT_BOOL pSendKeyboardEvents) PURE;
+    STDMETHOD(get_SendMouseClickEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseClickEvents) PURE;
+    STDMETHOD(put_SendMouseClickEvents)(VARIANT_BOOL pSendMouseClickEvents) PURE;
+    STDMETHOD(get_SendMouseMoveEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseMoveEvents) PURE;
+    STDMETHOD(put_SendMouseMoveEvents)(VARIANT_BOOL pSendMouseMoveEvents) PURE;
+    STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
+    STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
+    STDMETHOD(get_ClickToPlay)(VARIANT_BOOL __RPC_FAR *pClickToPlay) PURE;
+    STDMETHOD(put_ClickToPlay)(VARIANT_BOOL pClickToPlay) PURE;
+    STDMETHOD(get_AllowScan)(VARIANT_BOOL __RPC_FAR *pAllowScan) PURE;
+    STDMETHOD(put_AllowScan)(VARIANT_BOOL pAllowScan) PURE;
+    STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnableContextMenu) PURE;
+    STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnableContextMenu) PURE;
+    STDMETHOD(get_CursorType)(long __RPC_FAR *pCursorType) PURE;
+    STDMETHOD(put_CursorType)(long pCursorType) PURE;
+    STDMETHOD(get_CodecCount)(long __RPC_FAR *pCodecCount) PURE;
+    STDMETHOD(get_AllowChangeDisplaySize)(VARIANT_BOOL __RPC_FAR *pAllowChangeDisplaySize) PURE;
+    STDMETHOD(put_AllowChangeDisplaySize)( VARIANT_BOOL pAllowChangeDisplaySize) PURE;
+    STDMETHOD(get_IsDurationValid)(VARIANT_BOOL __RPC_FAR *pIsDurationValid) PURE;
+    STDMETHOD(get_OpenState)(long __RPC_FAR *pOpenState) PURE;
+    STDMETHOD(get_SendOpenStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendOpenStateChangeEvents) PURE;
+    STDMETHOD(put_SendOpenStateChangeEvents)(VARIANT_BOOL pSendOpenStateChangeEvents) PURE;
+    STDMETHOD(get_SendWarningEvents)( VARIANT_BOOL __RPC_FAR *pSendWarningEvents) PURE;
+    STDMETHOD(put_SendWarningEvents)(VARIANT_BOOL pSendWarningEvents) PURE;
+    STDMETHOD(get_SendErrorEvents)(VARIANT_BOOL __RPC_FAR *pSendErrorEvents) PURE;
+    STDMETHOD(put_SendErrorEvents)(VARIANT_BOOL pSendErrorEvents) PURE;
+    STDMETHOD(get_PlayState)(MPPlayStateConstants __RPC_FAR *pPlayState) PURE;
+    STDMETHOD(get_SendPlayStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendPlayStateChangeEvents) PURE;
+    STDMETHOD(put_SendPlayStateChangeEvents)(VARIANT_BOOL pSendPlayStateChangeEvents) PURE;
+    STDMETHOD(get_DisplaySize)(MPDisplaySizeConstants __RPC_FAR *pDisplaySize) PURE;
+    STDMETHOD(put_DisplaySize)(MPDisplaySizeConstants pDisplaySize) PURE;
+    STDMETHOD(get_InvokeURLs)(VARIANT_BOOL __RPC_FAR *pInvokeURLs) PURE;
+    STDMETHOD(put_InvokeURLs)(VARIANT_BOOL pInvokeURLs) PURE;
+    STDMETHOD(get_BaseURL)(BSTR __RPC_FAR *pbstrBaseURL) PURE;
+    STDMETHOD(put_BaseURL)(BSTR pbstrBaseURL) PURE;
+    STDMETHOD(get_DefaultFrame)(BSTR __RPC_FAR *pbstrDefaultFrame) PURE;
+    STDMETHOD(put_DefaultFrame)(BSTR pbstrDefaultFrame) PURE;
+    STDMETHOD(get_HasError)(VARIANT_BOOL __RPC_FAR *pHasError) PURE;
+    STDMETHOD(get_ErrorDescription)(BSTR __RPC_FAR *pbstrErrorDescription) PURE;
+    STDMETHOD(get_ErrorCode)(long __RPC_FAR *pErrorCode) PURE;
+    STDMETHOD(get_AnimationAtStart)(VARIANT_BOOL __RPC_FAR *pAnimationAtStart) PURE;
+    STDMETHOD(put_AnimationAtStart)(VARIANT_BOOL pAnimationAtStart) PURE;
+    STDMETHOD(get_TransparentAtStart)( VARIANT_BOOL __RPC_FAR *pTransparentAtStart) PURE;
+    STDMETHOD(put_TransparentAtStart)(VARIANT_BOOL pTransparentAtStart) PURE;
+    STDMETHOD(get_Volume)(long __RPC_FAR *pVolume) PURE;
+    STDMETHOD(put_Volume)(long pVolume) PURE;
+    STDMETHOD(get_Balance)(long __RPC_FAR *pBalance) PURE;
+    STDMETHOD(put_Balance)(long pBalance) PURE;
+    STDMETHOD(get_ReadyState)(MPReadyStateConstants __RPC_FAR *pValue) PURE;
+    STDMETHOD(get_SelectionStart)(double __RPC_FAR *pValue) PURE;
+    STDMETHOD(put_SelectionStart)(double pValue) PURE;
+    STDMETHOD(get_SelectionEnd)(double __RPC_FAR *pValue) PURE;
+    STDMETHOD(put_SelectionEnd)(double pValue) PURE;
+    STDMETHOD(get_ShowDisplay)(VARIANT_BOOL __RPC_FAR *Show) PURE;
+    STDMETHOD(put_ShowDisplay)(VARIANT_BOOL Show) PURE;
+    STDMETHOD(get_ShowControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
+    STDMETHOD(put_ShowControls)(VARIANT_BOOL Show) PURE;
+    STDMETHOD(get_ShowPositionControls)(VARIANT_BOOL __RPC_FAR *Show) PURE;
+    STDMETHOD(put_ShowPositionControls)(VARIANT_BOOL Show) PURE;
+    STDMETHOD(get_ShowTracker)(VARIANT_BOOL __RPC_FAR *Show) PURE;
+    STDMETHOD(put_ShowTracker)(VARIANT_BOOL Show) PURE;
+    STDMETHOD(get_EnablePositionControls)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
+    STDMETHOD(put_EnablePositionControls)(VARIANT_BOOL Enable) PURE;
+    STDMETHOD(get_EnableTracker)(VARIANT_BOOL __RPC_FAR *Enable) PURE;
+    STDMETHOD(put_EnableTracker)(VARIANT_BOOL Enable) PURE;
+    STDMETHOD(get_Enabled)(VARIANT_BOOL __RPC_FAR *pEnabled) PURE;
+    STDMETHOD(put_Enabled)(VARIANT_BOOL pEnabled) PURE;
+    STDMETHOD(get_DisplayForeColor)(VB_OLE_COLOR __RPC_FAR *ForeColor) PURE;
+    STDMETHOD(put_DisplayForeColor)(VB_OLE_COLOR ForeColor) PURE;
+    STDMETHOD(get_DisplayBackColor)(VB_OLE_COLOR __RPC_FAR *BackColor) PURE;
+    STDMETHOD(put_DisplayBackColor)(VB_OLE_COLOR BackColor) PURE;
+    STDMETHOD(get_DisplayMode)(MPDisplayModeConstants __RPC_FAR *pValue) PURE;
+    STDMETHOD(put_DisplayMode)(MPDisplayModeConstants pValue) PURE;
+    STDMETHOD(get_VideoBorder3D)(VARIANT_BOOL __RPC_FAR *pVideoBorderWidth) PURE;
+    STDMETHOD(put_VideoBorder3D)(VARIANT_BOOL pVideoBorderWidth) PURE;
+    STDMETHOD(get_VideoBorderWidth)(long __RPC_FAR *pVideoBorderWidth) PURE;
+    STDMETHOD(put_VideoBorderWidth)(long pVideoBorderWidth) PURE;
+    STDMETHOD(get_VideoBorderColor)(VB_OLE_COLOR __RPC_FAR *pVideoBorderWidth) PURE;
+    STDMETHOD(put_VideoBorderColor)(VB_OLE_COLOR pVideoBorderWidth) PURE;
+    STDMETHOD(get_ShowGotoBar)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
+    STDMETHOD(put_ShowGotoBar)(VARIANT_BOOL pbool) PURE;
+    STDMETHOD(get_ShowStatusBar)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
+    STDMETHOD(put_ShowStatusBar)(VARIANT_BOOL pbool) PURE;
+    STDMETHOD(get_ShowCaptioning)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
+    STDMETHOD(put_ShowCaptioning)(VARIANT_BOOL pbool) PURE;
+    STDMETHOD(get_ShowAudioControls)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
+    STDMETHOD(put_ShowAudioControls)(VARIANT_BOOL pbool) PURE;
+    STDMETHOD(get_CaptioningID)( BSTR __RPC_FAR *pstrText) PURE;
+    STDMETHOD(put_CaptioningID)(BSTR pstrText) PURE;
+    STDMETHOD(get_Mute)(VARIANT_BOOL __RPC_FAR *vbool) PURE;
+    STDMETHOD(put_Mute)(VARIANT_BOOL vbool) PURE;
+    STDMETHOD(get_CanPreview)(VARIANT_BOOL __RPC_FAR *pCanPreview) PURE;
+    STDMETHOD(get_PreviewMode)(VARIANT_BOOL __RPC_FAR *pPreviewMode) PURE;
+    STDMETHOD(put_PreviewMode)(VARIANT_BOOL pPreviewMode) PURE;
+    STDMETHOD(get_HasMultipleItems)(VARIANT_BOOL __RPC_FAR *pHasMuliItems) PURE;
+    STDMETHOD(get_Language)(long __RPC_FAR *pLanguage) PURE;
+    STDMETHOD(put_Language)(long pLanguage) PURE;
+    STDMETHOD(get_AudioStream)(long __RPC_FAR *pStream) PURE;
+    STDMETHOD(put_AudioStream)(long pStream) PURE;
+    STDMETHOD(get_SAMIStyle)(BSTR __RPC_FAR *pbstrStyle) PURE;
+    STDMETHOD(put_SAMIStyle)(BSTR pbstrStyle) PURE;
+    STDMETHOD(get_SAMILang)(BSTR __RPC_FAR *pbstrLang) PURE;
+    STDMETHOD(put_SAMILang)(BSTR pbstrLang) PURE;
+    STDMETHOD(get_SAMIFileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
+    STDMETHOD(put_SAMIFileName)(BSTR pbstrFileName) PURE;
+    STDMETHOD(get_StreamCount)( long __RPC_FAR *pStreamCount) PURE;
+    STDMETHOD(get_ClientId)(BSTR __RPC_FAR *pbstrClientId) PURE;
+    STDMETHOD(get_ConnectionSpeed)(long __RPC_FAR *plConnectionSpeed) PURE;
+    STDMETHOD(get_AutoSize)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
+    STDMETHOD(put_AutoSize)(VARIANT_BOOL pbool) PURE;
+    STDMETHOD(get_EnableFullScreenControls)(VARIANT_BOOL __RPC_FAR *pbVal) PURE;
+    STDMETHOD(put_EnableFullScreenControls)(VARIANT_BOOL pbVal) PURE;
+    STDMETHOD(get_ActiveMovie)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
+    STDMETHOD(get_NSPlay)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
+    STDMETHOD(get_WindowlessVideo)(VARIANT_BOOL __RPC_FAR *pbool) PURE;
+    STDMETHOD(put_WindowlessVideo)(VARIANT_BOOL pbool) PURE;
+    STDMETHOD(Play)(void) PURE;
+    STDMETHOD(Stop)(void) PURE;
+    STDMETHOD(Pause)(void) PURE;
+    STDMETHOD(GetMarkerTime)(long MarkerNum,
+                             double __RPC_FAR *pMarkerTime) PURE;
+    STDMETHOD(GetMarkerName)(long MarkerNum,
+                             BSTR __RPC_FAR *pbstrMarkerName) PURE;
+    STDMETHOD(AboutBox)(void) PURE;
+    STDMETHOD(GetCodecInstalled)(long CodecNum,
+                              VARIANT_BOOL __RPC_FAR *pCodecInstalled) PURE;
+    STDMETHOD(GetCodecDescription)(long CodecNum,
+                                 BSTR __RPC_FAR *pbstrCodecDescription) PURE;
+    STDMETHOD(GetCodecURL)(long CodecNum,
+                           BSTR __RPC_FAR *pbstrCodecURL) PURE;
+    STDMETHOD(GetMoreInfoURL)(MPMoreInfoType MoreInfoType,
+                              BSTR __RPC_FAR *pbstrMoreInfoURL) PURE;
+    STDMETHOD(GetMediaInfoString)(MPMediaInfoType MediaInfoType,
+                                  BSTR __RPC_FAR *pbstrMediaInfo) PURE;
+    STDMETHOD(Cancel)(void) PURE;
+    STDMETHOD(Open)(BSTR bstrFileName) PURE;
+    STDMETHOD(IsSoundCardEnabled)(VARIANT_BOOL __RPC_FAR *pbSoundCard) PURE;
+    STDMETHOD(Next)(void) PURE;
+    STDMETHOD(Previous)(void) PURE;
+    STDMETHOD(StreamSelect)(long StreamNum) PURE;
+    STDMETHOD(FastForward)(void) PURE;
+    STDMETHOD(FastReverse)(void) PURE;
+    STDMETHOD(GetStreamName)(long StreamNum,
+                             BSTR __RPC_FAR *pbstrStreamName) PURE;
+    STDMETHOD(GetStreamGroup)(long StreamNum,
+                              long __RPC_FAR *pStreamGroup) PURE;
+    STDMETHOD(GetStreamSelected)(long StreamNum, VARIANT_BOOL __RPC_FAR *pStreamSelected) PURE;
+};
+
+struct IMediaPlayer2 : public IMediaPlayer
+{
+    STDMETHOD(get_DVD)(struct IMediaPlayerDvd __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
+    STDMETHOD(GetMediaParameter)(long EntryNum, BSTR bstrParameterName, BSTR __RPC_FAR *pbstrParameterValue) PURE;
+    STDMETHOD(GetMediaParameterName(long EntryNum, long Index, BSTR __RPC_FAR *pbstrParameterName) PURE;
+    STDMETHOD(get_EntryCount)(long __RPC_FAR *pNumberEntries) PURE;
+    STDMETHOD(GetCurrentEntry)(long __RPC_FAR *pEntryNumber) PURE;
+    STDMETHOD(SetCurrentEntry)(long EntryNumber) PURE;
+    STDMETHOD(ShowDialog)(MPShowDialogConstants mpDialogIndex) PURE;
+};
+
+//---------------------------------------------------------------------------
+//  NETSHOW COM INTERFACES (dumped from nscompat.idl from MSVC COM Browser)
+//---------------------------------------------------------------------------
+
+struct INSOPlay : public IDispatch
+{
+    STDMETHOD(get_ImageSourceWidth)(long __RPC_FAR *pWidth) PURE;
+    STDMETHOD(get_ImageSourceHeight)(long __RPC_FAR *pHeight) PURE;
+    STDMETHOD(get_Duration)(double __RPC_FAR *pDuration) PURE;
+    STDMETHOD(get_Author)(BSTR __RPC_FAR *pbstrAuthor) PURE;
+    STDMETHOD(get_Copyright)(BSTR __RPC_FAR *pbstrCopyright) PURE;
+    STDMETHOD(get_Description)(BSTR __RPC_FAR *pbstrDescription) PURE;
+    STDMETHOD(get_Rating)(BSTR __RPC_FAR *pbstrRating) PURE;
+    STDMETHOD(get_Title)(BSTR __RPC_FAR *pbstrTitle) PURE;
+    STDMETHOD(get_SourceLink)(BSTR __RPC_FAR *pbstrSourceLink) PURE;
+    STDMETHOD(get_MarkerCount)(long __RPC_FAR *pMarkerCount) PURE;
+    STDMETHOD(get_CanScan)(VARIANT_BOOL __RPC_FAR *pCanScan) PURE;
+    STDMETHOD(get_CanSeek)(VARIANT_BOOL __RPC_FAR *pCanSeek) PURE;
+    STDMETHOD(get_CanSeekToMarkers)(VARIANT_BOOL __RPC_FAR *pCanSeekToMarkers) PURE;
+    STDMETHOD(get_CreationDate)(DATE __RPC_FAR *pCreationDate) PURE;
+    STDMETHOD(get_Bandwidth)(long __RPC_FAR *pBandwidth) PURE;
+    STDMETHOD(get_ErrorCorrection)(BSTR __RPC_FAR *pbstrErrorCorrection) PURE;
+    STDMETHOD(get_AutoStart)(VARIANT_BOOL __RPC_FAR *pAutoStart) PURE;
+    STDMETHOD(put_AutoStart)(VARIANT_BOOL pAutoStart) PURE;
+    STDMETHOD(get_AutoRewind)(VARIANT_BOOL __RPC_FAR *pAutoRewind) PURE;
+    STDMETHOD(put_AutoRewind)(VARIANT_BOOL pAutoRewind) PURE;
+    STDMETHOD(get_AllowChangeControlType)(VARIANT_BOOL __RPC_FAR *pAllowChangeControlType) PURE;
+    STDMETHOD(put_AllowChangeControlType)(VARIANT_BOOL pAllowChangeControlType) PURE;
+    STDMETHOD(get_InvokeURLs)(VARIANT_BOOL __RPC_FAR *pInvokeURLs) PURE;
+    STDMETHOD(put_InvokeURLs)(VARIANT_BOOL pInvokeURLs) PURE;
+    STDMETHOD(get_EnableContextMenu)(VARIANT_BOOL __RPC_FAR *pEnableContextMenu) PURE;
+    STDMETHOD(put_EnableContextMenu)(VARIANT_BOOL pEnableContextMenu) PURE;
+    STDMETHOD(get_TransparentAtStart)(VARIANT_BOOL __RPC_FAR *pTransparentAtStart) PURE;
+    STDMETHOD(put_TransparentAtStart)(VARIANT_BOOL pTransparentAtStart) PURE;
+    STDMETHOD(get_TransparentOnStop)(VARIANT_BOOL __RPC_FAR *pTransparentOnStop) PURE;
+    STDMETHOD(put_TransparentOnStop)(VARIANT_BOOL pTransparentOnStop) PURE;
+    STDMETHOD(get_ClickToPlay)(VARIANT_BOOL __RPC_FAR *pClickToPlay) PURE;
+    STDMETHOD(put_ClickToPlay)(VARIANT_BOOL pClickToPlay) PURE;
+    STDMETHOD(get_FileName)(BSTR __RPC_FAR *pbstrFileName) PURE;
+    STDMETHOD(put_FileName)(BSTR pbstrFileName) PURE;
+    STDMETHOD(get_CurrentPosition)(double __RPC_FAR *pCurrentPosition) PURE;
+    STDMETHOD(put_CurrentPosition)(double pCurrentPosition) PURE;
+    STDMETHOD(get_Rate)(double __RPC_FAR *pRate) PURE;
+    STDMETHOD(put_Rate)(double pRate) PURE;
+    STDMETHOD(get_CurrentMarker)(long __RPC_FAR *pCurrentMarker) PURE;
+    STDMETHOD(put_CurrentMarker)(long pCurrentMarker) PURE;
+    STDMETHOD(get_PlayCount)(long __RPC_FAR *pPlayCount) PURE;
+    STDMETHOD(put_PlayCount)(long pPlayCount) PURE;
+    STDMETHOD(get_CurrentState)(long __RPC_FAR *pCurrentState) PURE;
+    STDMETHOD(get_DisplaySize)(long __RPC_FAR *pDisplaySize) PURE;
+    STDMETHOD(put_DisplaySize)(long pDisplaySize) PURE;
+    STDMETHOD(get_MainWindow)(long __RPC_FAR *pMainWindow) PURE;
+    STDMETHOD(get_ControlType)(long __RPC_FAR *pControlType) PURE;
+    STDMETHOD(put_ControlType)(long pControlType) PURE;
+    STDMETHOD(get_AllowScan)(VARIANT_BOOL __RPC_FAR *pAllowScan) PURE;
+    STDMETHOD(put_AllowScan)(VARIANT_BOOL pAllowScan) PURE;
+    STDMETHOD(get_SendKeyboardEvents)(VARIANT_BOOL __RPC_FAR *pSendKeyboardEvents) PURE;
+    STDMETHOD(put_SendKeyboardEvents)(VARIANT_BOOL pSendKeyboardEvents) PURE;
+    STDMETHOD(get_SendMouseClickEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseClickEvents) PURE;
+    STDMETHOD(put_SendMouseClickEvents)(VARIANT_BOOL pSendMouseClickEvents) PURE;
+    STDMETHOD(get_SendMouseMoveEvents)(VARIANT_BOOL __RPC_FAR *pSendMouseMoveEvents) PURE;
+    STDMETHOD(put_SendMouseMoveEvents)(VARIANT_BOOL pSendMouseMoveEvents) PURE;
+    STDMETHOD(get_SendStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendStateChangeEvents) PURE;
+    STDMETHOD(put_SendStateChangeEvents)(VARIANT_BOOL pSendStateChangeEvents) PURE;
+    STDMETHOD(get_ReceivedPackets)(long __RPC_FAR *pReceivedPackets) PURE;
+    STDMETHOD(get_RecoveredPackets)(long __RPC_FAR *pRecoveredPackets) PURE;
+    STDMETHOD(get_LostPackets)(long __RPC_FAR *pLostPackets) PURE;
+    STDMETHOD(get_ReceptionQuality)(long __RPC_FAR *pReceptionQuality) PURE;
+    STDMETHOD(get_BufferingCount)(long __RPC_FAR *pBufferingCount) PURE;
+    STDMETHOD(get_CursorType)(long __RPC_FAR *pCursorType) PURE;
+    STDMETHOD(put_CursorType)(long pCursorType) PURE;
+    STDMETHOD(get_AnimationAtStart)(VARIANT_BOOL __RPC_FAR *pAnimationAtStart) PURE;
+    STDMETHOD(put_AnimationAtStart)(VARIANT_BOOL pAnimationAtStart) PURE;
+    STDMETHOD(get_AnimationOnStop)(VARIANT_BOOL __RPC_FAR *pAnimationOnStop) PURE;
+    STDMETHOD(put_AnimationOnStop)(VARIANT_BOOL pAnimationOnStop) PURE;
+    STDMETHOD(Play)(void) PURE;
+    STDMETHOD(Pause)(void) PURE;
+    STDMETHOD(Stop)(void) PURE;
+    STDMETHOD(GetMarkerTime)(long MarkerNum, double __RPC_FAR *pMarkerTime) PURE;
+    STDMETHOD(GetMarkerName)(long MarkerNum, BSTR __RPC_FAR *pbstrMarkerName) PURE;
+};
+
+struct INSPlay : public INSOPlay
+{
+    STDMETHOD(get_ChannelName)(BSTR __RPC_FAR *pbstrChannelName) PURE;
+    STDMETHOD(get_ChannelDescription)(BSTR __RPC_FAR *pbstrChannelDescription) PURE;
+    STDMETHOD(get_ChannelURL)(BSTR __RPC_FAR *pbstrChannelURL) PURE;
+    STDMETHOD(get_ContactAddress)(BSTR __RPC_FAR *pbstrContactAddress) PURE;
+    STDMETHOD(get_ContactPhone)(BSTR __RPC_FAR *pbstrContactPhone) PURE;
+    STDMETHOD(get_ContactEmail)(BSTR __RPC_FAR *pbstrContactEmail) PURE;
+    STDMETHOD(get_AllowChangeDisplaySize)(VARIANT_BOOL __RPC_FAR *pAllowChangeDisplaySize) PURE;
+    STDMETHOD(put_AllowChangeDisplaySize)(VARIANT_BOOL pAllowChangeDisplaySize) PURE;
+    STDMETHOD(get_CodecCount)(long __RPC_FAR *pCodecCount) PURE;
+    STDMETHOD(get_IsBroadcast)(VARIANT_BOOL __RPC_FAR *pIsBroadcast) PURE;
+    STDMETHOD(get_IsDurationValid)(VARIANT_BOOL __RPC_FAR *pIsDurationValid) PURE;
+    STDMETHOD(get_SourceProtocol)(long __RPC_FAR *pSourceProtocol) PURE;
+    STDMETHOD(get_OpenState)(long __RPC_FAR *pOpenState) PURE;
+    STDMETHOD(get_SendOpenStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendOpenStateChangeEvents) PURE;
+    STDMETHOD(put_SendOpenStateChangeEvents)(VARIANT_BOOL pSendOpenStateChangeEvents) PURE;
+    STDMETHOD(get_SendWarningEvents)(VARIANT_BOOL __RPC_FAR *pSendWarningEvents) PURE;
+    STDMETHOD(put_SendWarningEvents)(VARIANT_BOOL pSendWarningEvents) PURE;
+    STDMETHOD(get_SendErrorEvents)(VARIANT_BOOL __RPC_FAR *pSendErrorEvents) PURE;
+    STDMETHOD(put_SendErrorEvents)(VARIANT_BOOL pSendErrorEvents) PURE;
+    STDMETHOD(get_HasError)(VARIANT_BOOL __RPC_FAR *pHasError) PURE;
+    STDMETHOD(get_ErrorDescription)(BSTR __RPC_FAR *pbstrErrorDescription) PURE;
+    STDMETHOD(get_ErrorCode)(long __RPC_FAR *pErrorCode) PURE;
+    STDMETHOD(get_PlayState)(long __RPC_FAR *pPlayState) PURE;
+    STDMETHOD(get_SendPlayStateChangeEvents)(VARIANT_BOOL __RPC_FAR *pSendPlayStateChangeEvents) PURE;
+    STDMETHOD(put_SendPlayStateChangeEvents)(VARIANT_BOOL pSendPlayStateChangeEvents) PURE;
+    STDMETHOD(get_BufferingTime)(double __RPC_FAR *pBufferingTime) PURE;
+    STDMETHOD(put_BufferingTime)(double pBufferingTime) PURE;
+    STDMETHOD(get_UseFixedUDPPort)(VARIANT_BOOL __RPC_FAR *pUseFixedUDPPort) PURE;
+    STDMETHOD(put_UseFixedUDPPort)(VARIANT_BOOL pUseFixedUDPPort) PURE;
+    STDMETHOD(get_FixedUDPPort)(long __RPC_FAR *pFixedUDPPort) PURE;
+    STDMETHOD(put_FixedUDPPort)(long pFixedUDPPort) PURE;
+    STDMETHOD(get_UseHTTPProxy)(VARIANT_BOOL __RPC_FAR *pUseHTTPProxy) PURE;
+    STDMETHOD(put_UseHTTPProxy)(VARIANT_BOOL pUseHTTPProxy) PURE;
+    STDMETHOD(get_EnableAutoProxy)(VARIANT_BOOL __RPC_FAR *pEnableAutoProxy) PURE;
+    STDMETHOD(put_EnableAutoProxy)(VARIANT_BOOL pEnableAutoProxy) PURE;
+    STDMETHOD(get_HTTPProxyHost)(BSTR __RPC_FAR *pbstrHTTPProxyHost) PURE;
+    STDMETHOD(put_HTTPProxyHost)(BSTR pbstrHTTPProxyHost) PURE;
+    STDMETHOD(get_HTTPProxyPort)(long __RPC_FAR *pHTTPProxyPort) PURE;
+    STDMETHOD(put_HTTPProxyPort)(long pHTTPProxyPort) PURE;
+    STDMETHOD(get_EnableMulticast)(VARIANT_BOOL __RPC_FAR *pEnableMulticast) PURE;
+    STDMETHOD(put_EnableMulticast)(VARIANT_BOOL pEnableMulticast) PURE;
+    STDMETHOD(get_EnableUDP)(VARIANT_BOOL __RPC_FAR *pEnableUDP) PURE;
+    STDMETHOD(put_EnableUDP)(VARIANT_BOOL pEnableUDP) PURE;
+    STDMETHOD(get_EnableTCP)(VARIANT_BOOL __RPC_FAR *pEnableTCP) PURE;
+    STDMETHOD(put_EnableTCP)(VARIANT_BOOL pEnableTCP) PURE;
+    STDMETHOD(get_EnableHTTP)(VARIANT_BOOL __RPC_FAR *pEnableHTTP) PURE;
+    STDMETHOD(put_EnableHTTP)(VARIANT_BOOL pEnableHTTP) PURE;
+    STDMETHOD(get_BufferingProgress)(long __RPC_FAR *pBufferingProgress) PURE;
+    STDMETHOD(get_BaseURL)(BSTR __RPC_FAR *pbstrBaseURL) PURE;
+    STDMETHOD(put_BaseURL)(BSTR pbstrBaseURL) PURE;
+    STDMETHOD(get_DefaultFrame)(BSTR __RPC_FAR *pbstrDefaultFrame) PURE;
+    STDMETHOD(put_DefaultFrame)(BSTR pbstrDefaultFrame) PURE;
+    STDMETHOD(AboutBox))(void) PURE;
+    STDMETHOD(Cancel)(void) PURE;
+    STDMETHOD(GetCodecInstalled)(long CodecNum, VARIANT_BOOL __RPC_FAR *pCodecInstalled) PURE;
+    STDMETHOD(GetCodecDescription)(long CodecNum, BSTR __RPC_FAR *pbstrCodecDescription) PURE;
+    STDMETHOD(GetCodecURL)(long CodecNum, BSTR __RPC_FAR *pbstrCodecURL) PURE;
+    STDMETHOD(Open)(BSTR bstrFileName) PURE;
+};
+
+
+struct INSPlay1 : public INSPlay
+{
+    STDMETHOD(get_MediaPlayer)(IDispatch __RPC_FAR *__RPC_FAR *ppdispatch) PURE;
+};
+
+//---------------------------------------------------------------------------
+//  IWMP (PocketPC 2000) COM INTERFACES (dumped from PlayerOCX.idl)
+//---------------------------------------------------------------------------
+
+#ifdef __WXWINCE__
+
+struct IWMP : public IDispatch
+{
+public:
+    virtual /* [id][propput] */ HRESULT STDMETHODCALLTYPE put_AutoSize(
+        /* [in] */ VARIANT_BOOL vbool) = 0;
+
+    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_AutoSize(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbool) = 0;
+
+    virtual /* [id][propput] */ HRESULT STDMETHODCALLTYPE put_BorderStyle(
+        /* [in] */ long style) = 0;
+
+    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_BorderStyle(
+        /* [retval][out] */ long __RPC_FAR *pstyle) = 0;
+
+    virtual /* [id][propput] */ HRESULT STDMETHODCALLTYPE put_Enabled(
+        /* [in] */ VARIANT_BOOL vbool) = 0;
+
+    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_Enabled(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbool) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_FileName(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_FileName(
+        /* [in] */ BSTR newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Volume(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_Volume(
+        /* [in] */ long newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Mute(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_Mute(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_AutoStart(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_AutoStart(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_PlayCount(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_PlayCount(
+        /* [in] */ long newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ShowStatusBar(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_ShowStatusBar(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ShowAudioControls(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_ShowAudioControls(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ShowCaptioning(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_ShowCaptioning(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ShowControls(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_ShowControls(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ShowDisplay(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_ShowDisplay(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ShowGotoBar(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_ShowGotoBar(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ShowPositionControls(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_ShowPositionControls(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ShowTracker(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_ShowTracker(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Startup( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Shutdown( void) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Bandwidth(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_BaseURL(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_BaseURL(
+        /* [in] */ BSTR pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_BufferingCount(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_BufferingProgress(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_BufferingTime(
+        /* [retval][out] */ double __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_CanSeek(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_CanSeekToMarkers(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ChannelDescription(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ChannelName(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ChannelURL(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ClientID(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ConnectionSpeed(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ContactAddress(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ContactEmail(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ContactPhone(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentMarker(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentMarker(
+        /* [in] */ long newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_CurrentPosition(
+        /* [retval][out] */ double __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_CurrentPosition(
+        /* [in] */ double newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_DefaultFrame(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_DefaultFrame(
+        /* [in] */ BSTR newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Duration(
+        /* [retval][out] */ double __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_EntryCount(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ErrorCode(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ErrorDescription(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_HasError(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_HasMultipleItems(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ImageSourceHeight(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ImageSourceWidth(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_InvokeURLs(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_InvokeURLs(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_IsBroadcast(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_IsDurationValid(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_LostPackets(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_MarkerCount(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_OpenState(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_PlayState(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_PreviewMode(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_PreviewMode(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ReadyState(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ReceivedPackets(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ReceptionQuality(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_RecoveredPackets(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SAMIFileName(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SAMIFileName(
+        /* [in] */ BSTR newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SAMILang(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SAMILang(
+        /* [in] */ BSTR newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SAMIStyle(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SAMIStyle(
+        /* [in] */ BSTR newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SelectionEnd(
+        /* [retval][out] */ double __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SelectionEnd(
+        /* [in] */ double newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SelectionStart(
+        /* [retval][out] */ double __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SelectionStart(
+        /* [in] */ double newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SendErrorEvents(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SendErrorEvents(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SendKeyboardEvents(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SendKeyboardEvents(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SendMouseClickEvents(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SendMouseClickEvents(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SendMouseMoveEvents(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SendMouseMoveEvents(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SendOpenStateChangeEvents(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SendOpenStateChangeEvents(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SendPlayStateChangeEvents(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SendPlayStateChangeEvents(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SendWarningEvents(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_SendWarningEvents(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SourceLink(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE AboutBox( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Cancel( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetCodecDescription(
+        /* [in] */ long nCodec,
+        /* [retval][out] */ BSTR __RPC_FAR *pDescription) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetCodecInstalled(
+        /* [in] */ BSTR __RPC_FAR *pstrCodec,
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pIsInstalled) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetCurrentEntry(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetMarkerName(
+        /* [in] */ long nMarker,
+        /* [retval][out] */ BSTR __RPC_FAR *pMarkerName) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetMarkerTime(
+        /* [in] */ long nMarker,
+        /* [retval][out] */ double __RPC_FAR *pMarkerTime) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetMediaInfoString(
+        /* [in] */ long MPMediaInfoType,
+        /* [retval][out] */ BSTR __RPC_FAR *pstrMediaInfo) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Next( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Open(
+        BSTR pstrClip) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Pause( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Play( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Previous( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Stop( void) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Rate(
+        /* [retval][out] */ double __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_Rate(
+        /* [in] */ double newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_DisplaySize(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_DisplaySize(
+        /* [in] */ long newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_SourceProtocol(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ErrorCorrection(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE FinalConstruct( void) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_AllowChangeDisplaySize(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_AllowChangeDisplaySize(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_AllowScan(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_AllowScan(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_AnimationAtStart(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_AnimationAtStart(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_AudioStream(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_AudioStream(
+        /* [in] */ long newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_AutoRewind(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_AutoRewind(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Balance(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_Balance(
+        /* [in] */ long newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_CanPreview(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_CanScan(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_CaptioningID(
+        /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ClickToPlay(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_ClickToPlay(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_CodecCount(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_CreationDate(
+        /* [retval][out] */ DATE __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_CursorType(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_CursorType(
+        /* [in] */ long newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_DisplayBackColor(
+        /* [retval][out] */ VB_OLE_COLOR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_DisplayBackColor(
+        /* [in] */ VB_OLE_COLOR newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_DisplayForeColor(
+        /* [retval][out] */ VB_OLE_COLOR __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_DisplayForeColor(
+        /* [in] */ VB_OLE_COLOR newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_DisplayMode(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_DisplayMode(
+        /* [in] */ long newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_EnableContextMenu(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_EnableContextMenu(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_EnableFullScreenControls(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_EnableFullScreenControls(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_EnablePositionControls(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_EnablePositionControls(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_EnableTracker(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_EnableTracker(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_Language(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_StreamCount(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_TransparentAtStart(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_TransparentAtStart(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_VideoBorder3D(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_VideoBorder3D(
+        /* [in] */ VARIANT_BOOL newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_VideoBorderColor(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_VideoBorderColor(
+        /* [in] */ long newVal) = 0;
+
+    virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_VideoBorderWidth(
+        /* [retval][out] */ long __RPC_FAR *pVal) = 0;
+
+    virtual /* [helpstring][id][propput] */ HRESULT STDMETHODCALLTYPE put_VideoBorderWidth(
+        /* [in] */ long newVal) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE FastForward( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE FastReverse( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetCodecURL(
+        /* [retval][out] */ BSTR __RPC_FAR *pstrCodecURL) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetMediaParameter(
+        /* [in] */ long nParam,
+        BSTR szParameterName,
+        /* [retval][out] */ BSTR __RPC_FAR *pstrParameterValue) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetMediaParameterName(
+        /* [in] */ long nParam,
+        long nIndex,
+        /* [retval][out] */ BSTR __RPC_FAR *pstrParameterName) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetMoreInfoURL(
+        /* [retval][out] */ BSTR __RPC_FAR *pstrMoreInfoURL) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetStreamGroup(
+        /* [retval][out] */ BSTR __RPC_FAR *pstrStreamGroup) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetStreamName(
+        /* [retval][out] */ BSTR __RPC_FAR *pstrStreamName) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetStreamSelected(
+        /* [in] */ long nStream,
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *fIsSelected) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IsSoundCardEnabled(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *fIsEnabled) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE SetCurrentEntry(
+        long nValue) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE ShowDialog(
+        long nValue) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE StreamSelect(
+        long nSelect) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE OnWindowMessage(
+        UINT msg,
+        WPARAM wParam,
+        LPARAM lParam,
+        LRESULT __RPC_FAR *plResult) = 0;
+
+};
+
+
+#endif // CE
+
+//---------------------------------------------------------------------------
+// MISC COM INTERFACES
+//---------------------------------------------------------------------------
+typedef enum _FilterState
+{
+    State_Stopped,
+    State_Paused,
+    State_Running
+} FILTER_STATE;
+typedef enum _PinDirection {
+    PINDIR_INPUT,
+    PINDIR_OUTPUT
+} PIN_DIRECTION;
+
+typedef struct _FilterInfo {
+    WCHAR        achName[128];
+    struct IFilterGraph *pGraph;
+} FILTER_INFO;
+
+typedef struct _PinInfo {
+    struct IBaseFilter *pFilter;
+    PIN_DIRECTION dir;
+    WCHAR achName[128];
+} PIN_INFO;
+
+struct IBaseFilter;
+struct IPin;
+struct IEnumFilters;
+typedef struct  _MediaType {
+    GUID      majortype;
+    GUID      subtype;
+    BOOL      bFixedSizeSamples;
+    BOOL      bTemporalCompression;
+    ULONG     lSampleSize;
+    GUID      formattype;
+    IUnknown  *pUnk;
+    ULONG     cbFormat;
+    BYTE *pbFormat;
+} AM_MEDIA_TYPE;
+
+struct IFilterGraph : public IUnknown
+{
+    STDMETHOD(AddFilter)(IBaseFilter *, LPCWSTR) PURE;
+    STDMETHOD(RemoveFilter)(IBaseFilter *) PURE;
+    STDMETHOD(EnumFilters)(IEnumFilters **) PURE;
+    STDMETHOD(FindFilterByName)(LPCWSTR, IBaseFilter **) PURE;
+    STDMETHOD(ConnectDirect)(IPin *, IPin *, const AM_MEDIA_TYPE *) PURE;
+    STDMETHOD(Reconnect)(IPin *) PURE;
+    STDMETHOD(Disconnect)(IPin *) PURE;
+    STDMETHOD(SetDefaultSyncSource)() PURE;
+};
+
+struct IGraphBuilder : public IFilterGraph
+{
+    STDMETHOD(Connect)(IPin *, IPin *) PURE;
+    STDMETHOD(Render)(IPin *) PURE;
+    STDMETHOD(RenderFile)(LPCWSTR, LPCWSTR) PURE;
+    STDMETHOD(AddSourceFilter)(LPCWSTR, LPCWSTR, IBaseFilter **) PURE;
+    STDMETHOD(SetLogFile)(DWORD_PTR) PURE;
+    STDMETHOD(Abort)() PURE;
+    STDMETHOD(ShouldOperationContinue)() PURE;
+};
+
+struct IReferenceClock;
+struct IEnumPins;
+#define REFERENCE_TIME LONGLONG
+struct IMediaFilter : public IPersist
+{
+    STDMETHOD(Stop)( void) PURE;
+    STDMETHOD(Pause)( void) PURE;
+    STDMETHOD(Run)(REFERENCE_TIME tStart) PURE;
+    STDMETHOD(GetState)(DWORD dwMilliSecsTimeout,
+                       FILTER_STATE *State) PURE;
+    STDMETHOD(SetSyncSource)(IReferenceClock *pClock) PURE;
+    STDMETHOD(GetSyncSource)(IReferenceClock **pClock) PURE;
+};
+
+struct IBaseFilter : public IMediaFilter
+{
+    STDMETHOD(EnumPins)(IEnumPins **ppEnum) PURE;
+    STDMETHOD(FindPin)(LPCWSTR Id, IPin **ppPin) PURE;
+    STDMETHOD(QueryFilterInfo)(FILTER_INFO *pInfo) PURE;
+    STDMETHOD(JoinFilterGraph)(IFilterGraph *pGraph, LPCWSTR pName) PURE;
+    STDMETHOD(QueryVendorInfo)(LPWSTR *pVendorInfo) PURE;
+};
+
+
+//---------------------------------------------------------------------------
+//
+//  wxAMMediaBackend
+//
+//---------------------------------------------------------------------------
+
+typedef BOOL (WINAPI* LPAMGETERRORTEXT)(HRESULT, wxChar *, DWORD);
+
+class WXDLLIMPEXP_MEDIA wxAMMediaBackend : public wxMediaBackendCommonBase
+{
+public:
+    wxAMMediaBackend();
+    virtual ~wxAMMediaBackend();
+
+    virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
+                                     wxWindowID id,
+                                     const wxPoint& pos,
+                                     const wxSize& size,
+                                     long style,
+                                     const wxValidator& validator,
+                                     const wxString& name);
+
+    virtual bool Play();
+    virtual bool Pause();
+    virtual bool Stop();
+
+    virtual bool Load(const wxString& fileName);
+    virtual bool Load(const wxURI& location);
+    virtual bool Load(const wxURI& location, const wxURI& proxy);
+
+    bool DoLoad(const wxString& location);
+    void FinishLoad();
+
+    virtual wxMediaState GetState();
+
+    virtual bool SetPosition(wxLongLong where);
+    virtual wxLongLong GetPosition();
+    virtual wxLongLong GetDuration();
+
+    virtual void Move(int x, int y, int w, int h);
+    wxSize GetVideoSize() const;
+
+    virtual double GetPlaybackRate();
+    virtual bool SetPlaybackRate(double);
+
+    virtual double GetVolume();
+    virtual bool SetVolume(double);
+
+    virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
+
+    void DoGetDownloadProgress(wxLongLong*, wxLongLong*);
+    virtual wxLongLong GetDownloadProgress()
+    {
+        wxLongLong progress, total;
+        DoGetDownloadProgress(&progress, &total);
+        return progress;
+    }
+    virtual wxLongLong GetDownloadTotal()
+    {
+        wxLongLong progress, total;
+        DoGetDownloadProgress(&progress, &total);
+        return total;
+    }
+
+    wxActiveXContainer* m_pAX;   // ActiveX host
+#ifdef __WXWINCE__
+    IWMP* m_pWMP;
+
+    IWMP* GetMP() {return m_pWMP;}
+    IWMP* GetAM() {return m_pWMP;}
+#else
+    IActiveMovie* m_pAM;
+    IMediaPlayer* m_pMP;
+
+    IMediaPlayer* GetMP() {return m_pMP;}
+    IActiveMovie* GetAM() {return m_pAM;}
+#endif
+    wxSize m_bestSize;  // Cached size
+
+#ifdef __WXDEBUG__  // Stuff for getting useful debugging strings
+    wxDynamicLibrary m_dllQuartz;
+    LPAMGETERRORTEXT m_lpAMGetErrorText;
+    wxString GetErrorString(HRESULT hrdsv);
+#endif // __WXDEBUG__
+
+    friend class wxAMMediaEvtHandler;
+    DECLARE_DYNAMIC_CLASS(wxAMMediaBackend)
+};
+
+class WXDLLIMPEXP_MEDIA wxAMMediaEvtHandler : public wxEvtHandler
+{
+public:
+    wxAMMediaEvtHandler(wxAMMediaBackend *amb) :
+       m_amb(amb), m_bLoadEventSent(false)
+    {
+        m_amb->m_pAX->Connect(m_amb->m_pAX->GetId(),
+            wxEVT_ACTIVEX,
+            wxActiveXEventHandler(wxAMMediaEvtHandler::OnActiveX),
+            NULL, this
+                              );
+    }
+
+    void OnActiveX(wxActiveXEvent& event);
+
+private:
+    wxAMMediaBackend *m_amb;
+    bool m_bLoadEventSent; // Whether or not FinishLoaded was already called
+                           // prevents it being called multiple times
+
+    DECLARE_NO_COPY_CLASS(wxAMMediaEvtHandler)
+};
+
+//===========================================================================
+//  IMPLEMENTATION
+//===========================================================================
+
+//---------------------------------------------------------------------------
+//
+// wxAMMediaBackend
+//
+//---------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxAMMediaBackend, wxMediaBackend)
+
+//---------------------------------------------------------------------------
+// Usual debugging macros
+//---------------------------------------------------------------------------
+#ifdef __WXDEBUG__
+#define MAX_ERROR_TEXT_LEN 160
+
+// Get the error string for Active Movie
+wxString wxAMMediaBackend::GetErrorString(HRESULT hrdsv)
+{
+    wxChar szError[MAX_ERROR_TEXT_LEN];
+    if( m_lpAMGetErrorText != NULL &&
+       (*m_lpAMGetErrorText)(hrdsv, szError, MAX_ERROR_TEXT_LEN) == 0)
+    {
+        return wxString::Format(wxT("DirectShow error \"%s\" \n")
+                                     wxT("(numeric %X)\n")
+                                     wxT("occured"),
+                                     szError, (int)hrdsv);
+    }
+    else
+    {
+        return wxString::Format(wxT("Unknown error \n")
+                                     wxT("(numeric %X)\n")
+                                     wxT("occured"),
+                                     (int)hrdsv);
+    }
+}
+
+#define wxAMFAIL(x) wxFAIL_MSG(GetErrorString(x));
+#define wxVERIFY(x) wxASSERT((x))
+#define wxAMLOG(x) wxLogDebug(GetErrorString(x))
+#else
+#define wxAMVERIFY(x) (x)
+#define wxVERIFY(x) (x)
+#define wxAMLOG(x)
+#define wxAMFAIL(x)
+#endif
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend Constructor
+//---------------------------------------------------------------------------
+wxAMMediaBackend::wxAMMediaBackend()
+                 :m_pAX(NULL),
+#ifdef __WXWINCE__
+                  m_pWMP(NULL)
+#else
+                  m_pAM(NULL),
+                  m_pMP(NULL)
+#endif
+{
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend Destructor
+//---------------------------------------------------------------------------
+wxAMMediaBackend::~wxAMMediaBackend()
+{
+    if(m_pAX)
+    {
+        m_pAX->DissociateHandle();
+        delete m_pAX;
+#ifndef __WXWINCE__
+        m_pAM->Release();
+#endif
+
+        if (GetMP())
+            GetMP()->Release();
+
+        m_ctrl->PopEventHandler(true);
+    }
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::CreateControl
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
+                                     wxWindowID id,
+                                     const wxPoint& pos,
+                                     const wxSize& size,
+                                     long style,
+                                     const wxValidator& validator,
+                                     const wxString& name)
+{
+    // First get the AMGetErrorText procedure in debug
+    // mode for more meaningful messages
+#ifdef __WXDEBUG__
+    if ( m_dllQuartz.Load(_T("quartz.dll"), wxDL_VERBATIM) )
+    {
+        m_lpAMGetErrorText = (LPAMGETERRORTEXT)
+                                m_dllQuartz.GetSymbolAorW(wxT("AMGetErrorText"));
+    }
+#endif // __WXDEBUG__
+
+
+
+#ifdef __WXWINCE__
+   CLSID clsid;
+
+   // Try progids first - *.WMP is PocketPC and Mediaplayer.1 is CE.NET
+   // later versions support straight creation from CLSID
+   if (CLSIDFromProgID(L"WPCEOCX.WMP", &clsid) != S_OK &&
+       CLSIDFromProgID(L"MediaPlayer.MediaPlayer.1", &clsid) != S_OK)
+   {
+       clsid = CLSID_MediaPlayer;
+   }
+
+   // While the CLSID is the same as CLSID_MediaPlayer
+   // CE only supports the IWMP interface
+   if ( ::CoCreateInstance(clsid, NULL,
+                                 CLSCTX_INPROC_SERVER,
+                                 IID_IWMP, (void**)&m_pWMP) != 0 )
+   {
+           return false;
+   }
+
+#else
+    // Now determine which (if any) media player interface is
+    // available - IMediaPlayer or IActiveMovie
+    if( ::CoCreateInstance(CLSID_MediaPlayer, NULL,
+                                  CLSCTX_INPROC_SERVER,
+                                  IID_IMediaPlayer, (void**)&m_pMP) != 0 )
+    {
+        if( ::CoCreateInstance(CLSID_ActiveMovie, NULL,
+                                  CLSCTX_INPROC_SERVER,
+                                  IID_IActiveMovie, (void**)&m_pAM) != 0 )
+            return false;
+        m_pAM->QueryInterface(IID_IMediaPlayer, (void**)&m_pMP);
+    }
+    else
+    {
+        m_pMP->QueryInterface(IID_IActiveMovie, (void**)&m_pAM);
+    }
+#endif
+
+    //
+    // Create window
+    // By default wxWindow(s) is created with a border -
+    // so we need to get rid of those
+    //
+    // Since we don't have a child window like most other
+    // backends, we don't need wxCLIP_CHILDREN
+    //
+    if ( !ctrl->wxControl::Create(parent, id, pos, size,
+                            (style & ~wxBORDER_MASK) | wxBORDER_NONE,
+                            validator, name) )
+        return false;
+
+    //
+    // Now create the ActiveX container along with the media player
+    // interface and query them
+    //
+    m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
+    m_pAX = new wxActiveXContainer(ctrl,
+#ifdef __WXWINCE__
+                IID_IWMP, m_pWMP
+#else
+                m_pMP ? IID_IMediaPlayer : IID_IActiveMovie, m_pAM
+#endif
+                                  );
+    // Connect for events
+    m_ctrl->PushEventHandler(new wxAMMediaEvtHandler(this));
+
+    //
+    //  Here we set up wx-specific stuff for the default
+    //  settings wxMediaCtrl says it will stay to
+    //
+    if(GetMP())
+    {
+        GetMP()->put_DisplaySize(mpFitToSize);
+#ifndef __WXWINCE__ // Not in CE's IWMP
+        // TODO: Unsure what actual effect this has
+        // In DirectShow Windowless video results in less delay when
+        // dragging, for example - but this doesn't appear to really do anything
+        // in practice (it may be something different...)...
+        GetMP()->put_WindowlessVideo(VARIANT_TRUE);
+#endif
+
+    }
+#ifndef __WXWINCE__ // Not in CE's IWMP
+    else
+        GetAM()->put_MovieWindowSize(amvDoubleOriginalSize);
+#endif
+
+    // by default true
+    GetAM()->put_AutoStart(VARIANT_FALSE);
+    // by default enabled
+    wxAMMediaBackend::ShowPlayerControls(wxMEDIACTRLPLAYERCONTROLS_NONE);
+    // by default with AM only 0.5
+    wxAMMediaBackend::SetVolume(1.0);
+
+    // don't erase the background of our control window so that resizing is a
+    // bit smoother
+    m_ctrl->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
+
+    // success
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::Load (file version)
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::Load(const wxString& fileName)
+{
+    return DoLoad(fileName);
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::Load (URL Version)
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::Load(const wxURI& location)
+{
+    //  Turn off loading from a proxy as user
+    //  may have set it previously
+    INSPlay* pPlay = NULL;
+    GetAM()->QueryInterface(IID_INSPlay, (void**) &pPlay);
+    if(pPlay)
+    {
+        pPlay->put_UseHTTPProxy(VARIANT_FALSE);
+        pPlay->Release();
+    }
+
+    return DoLoad(location.BuildURI());
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::Load (URL Version with Proxy)
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::Load(const wxURI& location, const wxURI& proxy)
+{
+    // Set the proxy of the NETSHOW interface
+    INSPlay* pPlay = NULL;
+    GetAM()->QueryInterface(IID_INSPlay, (void**) &pPlay);
+
+    if(pPlay)
+    {
+        pPlay->put_UseHTTPProxy(VARIANT_TRUE);
+        pPlay->put_HTTPProxyHost(wxBasicString(proxy.GetServer()).Get());
+        pPlay->put_HTTPProxyPort(wxAtoi(proxy.GetPort()));
+        pPlay->Release();
+    }
+
+    return DoLoad(location.BuildURI());
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::DoLoad
+//
+// Called by all functions - this actually renders
+// the file and sets up the filter graph
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::DoLoad(const wxString& location)
+{
+    HRESULT hr;
+
+    // Play the movie the normal way through the embedded
+    // WMP.  Supposively Open is better in theory because
+    // the docs say its async and put_FileName is not -
+    // but in practice they both seem to be async anyway
+    if(GetMP())
+        hr = GetMP()->Open( wxBasicString(location).Get() );
+    else
+        hr = GetAM()->put_FileName( wxBasicString(location).Get() );
+
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return false;
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::FinishLoad
+//
+// Called when the media has finished loaded and is ready to play
+//
+// Here we get the original size of the video and
+// send the loaded event to our watcher :).
+//---------------------------------------------------------------------------
+void wxAMMediaBackend::FinishLoad()
+{
+    // Get the original video size
+    GetAM()->get_ImageSourceWidth((long*)&m_bestSize.x);
+    GetAM()->get_ImageSourceHeight((long*)&m_bestSize.y);
+
+    NotifyMovieLoaded();
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::ShowPlayerControls
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
+{
+    // Note that IMediaPlayer doesn't have a statusbar by
+    // default but IActiveMovie does - so lets try to keep
+    // the interface consistant
+    if(!flags)
+    {
+        GetAM()->put_Enabled(VARIANT_FALSE);
+        GetAM()->put_ShowControls(VARIANT_FALSE);
+        if(GetMP())
+            GetMP()->put_ShowStatusBar(VARIANT_FALSE);
+    }
+    else
+    {
+        GetAM()->put_Enabled(VARIANT_TRUE);
+        GetAM()->put_ShowControls(VARIANT_TRUE);
+
+        GetAM()->put_ShowPositionControls(
+                (flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ?
+                VARIANT_TRUE : VARIANT_FALSE);
+
+        if(GetMP())
+        {
+            GetMP()->put_ShowStatusBar(VARIANT_TRUE);
+            GetMP()->put_ShowAudioControls(
+                (flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ?
+                VARIANT_TRUE : VARIANT_FALSE);
+        }
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::Play
+//
+// Plays the stream.  If it is non-seekable, it will restart it (implicit).
+//
+// Note that we use SUCCEEDED here because run/pause/stop tend to be overly
+// picky and return warnings on pretty much every call
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::Play()
+{
+    // Actually try to play the movie (will fail if not loaded completely)
+#ifdef __WXWINCE__
+    HRESULT hr = m_pWMP->Play();
+#else
+    HRESULT hr = GetAM()->Run();
+#endif
+    if(SUCCEEDED(hr))
+    {
+       return true;
+    }
+    wxAMLOG(hr);
+    return false;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::Pause
+//
+// Pauses the stream.
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::Pause()
+{
+    HRESULT hr = GetAM()->Pause();
+    if(SUCCEEDED(hr))
+        return true;
+    wxAMLOG(hr);
+    return false;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::Stop
+//
+// Stops the stream.
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::Stop()
+{
+    HRESULT hr = GetAM()->Stop();
+    if(SUCCEEDED(hr))
+    {
+        // Seek to beginning
+        wxAMMediaBackend::SetPosition(0);
+        return true;
+    }
+    wxAMLOG(hr);
+    return false;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::SetPosition
+//
+// 1) Translates the current position's time to directshow time,
+//    which is in a scale of 1 second (in a double)
+// 2) Sets the play position of the IActiveMovie interface -
+//    passing NULL as the stop position means to keep the old
+//    stop position
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::SetPosition(wxLongLong where)
+{
+    HRESULT hr = GetAM()->put_CurrentPosition(
+                        ((LONGLONG)where.GetValue()) / 1000.0
+                                     );
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return false;
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::GetPosition
+//
+// 1) Obtains the current play and stop positions from IMediaSeeking
+// 2) Returns the play position translated to our time base
+//---------------------------------------------------------------------------
+wxLongLong wxAMMediaBackend::GetPosition()
+{
+    double outCur;
+    HRESULT hr = GetAM()->get_CurrentPosition(&outCur);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return 0;
+    }
+
+    // h,m,s,milli - outCur is in 1 second (double)
+    outCur *= 1000;
+    wxLongLong ll;
+    ll.Assign(outCur);
+
+    return ll;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::GetVolume
+//
+// Gets the volume through the IActiveMovie interface -
+// value ranges from 0 (MAX volume) to -10000 (minimum volume).
+// -100 per decibel (Logorithmic in 0.01db per step).
+//---------------------------------------------------------------------------
+double wxAMMediaBackend::GetVolume()
+{
+    long lVolume;
+    HRESULT hr = GetAM()->get_Volume(&lVolume);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return 0.0;
+    }
+
+    // Volume conversion from Greg Hazel
+    double dVolume = (double)lVolume / 125;
+
+    // convert to 0 to 1
+    dVolume = pow(10.0, dVolume/20.0);
+    // handle -INF
+    dVolume *= 1 + pow(10.0, -5.0);
+    dVolume -= pow(10.0, -5.0);
+    return dVolume;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::SetVolume
+//
+// Sets the volume through the IActiveMovie interface -
+// value ranges from 0 (MAX volume) to -10000 (minimum volume).
+// -100 per decibel (Logorithmic in 0.01db per step).
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::SetVolume(double dVolume)
+{
+    // Volume conversion from Greg Hazel
+    long lVolume;
+    // handle -INF
+    dVolume *= 1 - pow(10.0, -5.0);
+    dVolume += pow(10.0, -5.0);
+    // convert to -100db to 0db
+    dVolume = 20 * log10(dVolume);
+    // scale to -10000 to 0
+    lVolume = (long)(125 * dVolume);
+
+    HRESULT hr = GetAM()->put_Volume( lVolume );
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return false;
+    }
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::GetDuration
+//
+// 1) Obtains the duration of the media from IActiveMovie
+// 2) Converts that value to our time base, and returns it
+//
+// NB: With VBR MP3 files the default DirectShow MP3 render does not
+// read the Xing header correctly, resulting in skewed values for duration
+// and seeking
+//---------------------------------------------------------------------------
+wxLongLong wxAMMediaBackend::GetDuration()
+{
+    double outDuration;
+    HRESULT hr = GetAM()->get_Duration(&outDuration);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return 0;
+    }
+
+    // h,m,s,milli - outDuration is in 1 second (double)
+    outDuration *= 1000;
+    wxLongLong ll;
+    ll.Assign(outDuration);
+
+    return ll;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::GetState
+//
+// Returns the cached state
+//---------------------------------------------------------------------------
+wxMediaState wxAMMediaBackend::GetState()
+{
+    StateConstants nState;
+#ifdef __WXWINCE__
+    HRESULT hr = m_pWMP->get_PlayState((long*)&nState);
+#else
+    HRESULT hr = GetAM()->get_CurrentState(&nState);
+#endif
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return wxMEDIASTATE_STOPPED;
+    }
+
+    return (wxMediaState)nState;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::GetPlaybackRate
+//
+// Pretty simple way of obtaining the playback rate from
+// the IActiveMovie interface
+//---------------------------------------------------------------------------
+double wxAMMediaBackend::GetPlaybackRate()
+{
+    double dRate;
+    HRESULT hr = GetAM()->get_Rate(&dRate);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return 0.0;
+    }
+    return dRate;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::SetPlaybackRate
+//
+// Sets the playback rate of the media - DirectShow is pretty good
+// about this, actually
+//---------------------------------------------------------------------------
+bool wxAMMediaBackend::SetPlaybackRate(double dRate)
+{
+    HRESULT hr = GetAM()->put_Rate(dRate);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return false;
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::GetDownloadXXX
+//
+// Queries for and gets the total size of the file and the current
+// progress in downloading that file from the IAMOpenProgress
+// interface from the media player interface's filter graph
+//---------------------------------------------------------------------------
+void wxAMMediaBackend::DoGetDownloadProgress(wxLongLong* pLoadProgress,
+                                             wxLongLong* pLoadTotal)
+{
+#ifndef __WXWINCE__
+    LONGLONG loadTotal = 0, loadProgress = 0;
+    IUnknown* pFG;
+    IAMOpenProgress* pOP;
+    HRESULT hr;
+    hr = m_pAM->get_FilterGraph(&pFG);
+    if(SUCCEEDED(hr))
+    {
+        hr = pFG->QueryInterface(IID_IAMOpenProgress, (void**)&pOP);
+        if(SUCCEEDED(hr))
+    {
+            hr = pOP->QueryProgress(&loadTotal, &loadProgress);
+            pOP->Release();
+        }
+        pFG->Release();
+    }
+
+    if(SUCCEEDED(hr))
+    {
+        *pLoadProgress = loadProgress;
+        *pLoadTotal = loadTotal;
+    }
+    else
+#endif
+    {
+        // When not loading from a URL QueryProgress will return
+        // E_NOINTERFACE or whatever
+        // wxAMFAIL(hr);
+        *pLoadProgress = 0;
+        *pLoadTotal = 0;
+    }
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::GetVideoSize
+//
+// Obtains the cached original video size
+//---------------------------------------------------------------------------
+wxSize wxAMMediaBackend::GetVideoSize() const
+{
+    return m_bestSize;
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::Move
+//
+// We take care of this in our redrawing
+//---------------------------------------------------------------------------
+void wxAMMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
+                            int WXUNUSED(w), int WXUNUSED(h))
+{
+}
+
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::OnActiveX
+//
+// Handle events sent from our activex control (IActiveMovie/IMediaPlayer).
+//
+// The weird numbers in the switch statement here are "dispatch ids"
+// (the numbers in the id field like ( id(xxx) ) ) from amcompat.idl
+// and msdxm.idl.
+//---------------------------------------------------------------------------
+void wxAMMediaEvtHandler::OnActiveX(wxActiveXEvent& event)
+{
+    switch(event.GetDispatchId())
+    {
+#ifndef __WXWINCE__
+    case 0x00000001: // statechange in IActiveMovie
+    case 0x00000bc4: // playstatechange in IMediaPlayer
+#else
+    case 0x00000011: // 17 == playstatechange on IWMP
+#endif
+        if(event.ParamCount() >= 2)
+        {
+            switch (event[1].GetInteger())
+            {
+            case 0: // stopping
+                if( m_amb->wxAMMediaBackend::GetPosition() ==
+                    m_amb->wxAMMediaBackend::GetDuration() )
+                {
+                    if ( m_amb->SendStopEvent() )
+                    {
+                        // Seek to beginning of movie
+                        m_amb->wxAMMediaBackend::SetPosition(0);
+
+                        // send the event to our child
+                        m_amb->QueueFinishEvent();
+                    }
+                }
+                else
+                {
+                    m_amb->QueueStopEvent();
+                }
+                break;
+            case 1: // pause
+                m_amb->QueuePauseEvent();
+                break;
+            case 2: // play
+                m_amb->QueuePlayEvent();
+                break;
+            default:
+                break;
+            }
+        }
+        else
+            event.Skip();
+        break;
+
+#ifndef __WXWINCE__
+    case 0x00000032: // opencomplete in IActiveMovie
+        if(!m_bLoadEventSent)
+        {
+            m_amb->FinishLoad();
+        }
+        break;
+
+    case 0xfffffd9f: // readystatechange in IActiveMovie2 and IMediaPlayer
+#else
+    case 0x00000013: // 19 == readystatechange in IWMP
+#endif
+        if(event.ParamCount() >= 1)
+        {
+            if(event[0].GetInteger() == 0)
+            {
+                m_bLoadEventSent = false;
+            }
+            // Originally this was >= 3 here but on 3 we can't get the
+            // size of the video (will error) - however on 4
+            // it won't play on downloaded things until it is
+            // completely downloaded so we use the lesser of two evils...
+            else if(event[0].GetInteger() == 3 &&
+                !m_bLoadEventSent)
+            {
+                m_bLoadEventSent = true;
+                m_amb->FinishLoad();
+            }
+        }
+        else
+            event.Skip();
+        break;
+
+    default:
+        event.Skip();
+        return;
+    }
+}
+
+//---------------------------------------------------------------------------
+// End of wxAMMediaBackend
+//---------------------------------------------------------------------------
+
+// in source file that contains stuff you don't directly use
+#include "wx/html/forcelnk.h"
+FORCE_LINK_ME(wxmediabackend_am)
+
+//---------------------------------------------------------------------------
+//  End wxMediaCtrl Compilation Guard and this file
+//---------------------------------------------------------------------------
+#endif // wxUSE_MEDIACTRL
\ No newline at end of file
diff --git a/src/msw/mediactrl_wmp10.cpp b/src/msw/mediactrl_wmp10.cpp
new file mode 100644 (file)
index 0000000..e1f8e1d
--- /dev/null
@@ -0,0 +1,1521 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        src/msw/mediactrl_wmp10.cpp
+// Purpose:     Windows Media Player 9/10 Media Backend for Windows
+// Author:      Ryan Norton <wxprojects@comcast.net>
+// Modified by:
+// Created:     11/07/04
+// RCS-ID:      $Id$
+// Copyright:   (c) Ryan Norton
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+//-----------------Introduction----------------------------------------------
+// This backend is for Desktops with either WMP 9 or 10 and Windows
+// mobile (5.0, some 2003 SmartPhones etc.) WMP 10 only (9 has no automation
+// interface but you can hack it with message hacks to play through
+// a currently running instance of media player).
+//
+// There are quite a few WMP 10 interfaces and unlike other media
+// backends we actually set it to automatically play files as it has
+// as huge caveat that you cannot (technically) obtain media information
+// from IWMPMedia including duration and video size until a media file
+// has literally started to play. There is a hack (and indeed we have
+// it within this file) to enable duration getting from a non-playing
+// file, but there is no hack I (RN) know of to get the video size from
+// a file that isn't playing.
+//
+// The workaround for this is to send the wxEVT_MEDIA_LOADED when the file
+// is about to be played - and if the user didn't change the state of the
+// media (m_bWasStateChanged), when set it back to the stop state.
+//
+// The ActiveX control itself is particularily stubborn, calling
+// IOleInPlaceSite::OnPosRectChange every file change trying to set itself
+// to something different then what we told it to before.
+//
+// The docs are at
+// http://msdn.microsoft.com/library/en-us/wmplay10/mmp_sdk/windowsmediaplayer10sdk.asp
+
+//===========================================================================
+//  DECLARATIONS
+//===========================================================================
+
+//---------------------------------------------------------------------------
+// Pre-compiled header stuff
+//---------------------------------------------------------------------------
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+//---------------------------------------------------------------------------
+// MediaCtrl include
+//---------------------------------------------------------------------------
+#include "wx/mediactrl.h"
+
+//---------------------------------------------------------------------------
+// Compilation guard
+//---------------------------------------------------------------------------
+#if wxUSE_MEDIACTRL
+
+//---------------------------------------------------------------------------
+// WX Includes
+//---------------------------------------------------------------------------
+#include "wx/log.h"         // wxLogDebug
+#include "wx/msw/private.h" // user info and wndproc setting/getting
+#include "wx/msw/ole/activex.h" // wxActiveXContainer - COM-specific stuff
+
+//---------------------------------------------------------------------------
+// ATL Includes - define WXTEST_ATL if you
+// want to use CAxWindow instead of wxActiveXContainer (note that
+// this is mainly for testing as the activex events arn't implemented here)
+//---------------------------------------------------------------------------
+#if 0
+    #define WXTEST_ATL
+#endif
+
+#ifdef WXTEST_ATL
+    #include <atlbase.h>
+    CComModule _Module;
+    #define min(x,y) (x < y ? x : y)
+    #include <atlcom.h>
+    #include <atlhost.h>
+    #include <atlctl.h>
+#endif
+
+//---------------------------------------------------------------------------
+// Other defines
+//---------------------------------------------------------------------------
+
+// disable "cast truncates constant value" for VARIANT_BOOL values
+// passed as parameters in VC6
+#ifdef _MSC_VER
+#pragma warning (disable:4310)
+#endif
+
+// error logger for HRESULTS (nothing really now)
+#define wxWMP10LOG(x)
+
+//---------------------------------------------------------------------------
+// Various definitions dumped from wmp.IDL
+//---------------------------------------------------------------------------
+
+// CLSID_WMP10ALT is on CE and in some MS docs - on others it is the plain ver
+const CLSID CLSID_WMP10              = {0x6BF52A50,0x394A,0x11D3,{0xB1,0x53,0x00,0xC0,0x4F,0x79,0xFA,0xA6}};
+const CLSID CLSID_WMP10ALT           = {0x6BF52A52,0x394A,0x11D3,{0xB1,0x53,0x00,0xC0,0x4F,0x79,0xFA,0xA6}};
+
+const IID IID_IWMPSettings = {0x9104D1AB,0x80C9,0x4FED,{0xAB,0xF0,0x2E,0x64,0x17,0xA6,0xDF,0x14}};
+const IID IID_IWMPCore = {0xD84CCA99,0xCCE2,0x11D2,{0x9E,0xCC,0x00,0x00,0xF8,0x08,0x59,0x81}};
+#ifndef WXTEST_ATL
+    const IID IID_IWMPPlayer = {0x6BF52A4F,0x394A,0x11D3,{0xB1,0x53,0x00,0xC0,0x4F,0x79,0xFA,0xA6}};
+#endif
+
+const IID IID_IWMPMedia = {0x94D55E95,0x3FAC,0x11D3,{0xB1,0x55,0x00,0xC0,0x4F,0x79,0xFA,0xA6}};
+const IID IID_IWMPControls = {0x74C09E02,0xF828,0x11D2,{0xA7,0x4B,0x00,0xA0,0xC9,0x05,0xF3,0x6E}};
+const IID IID_IWMPPlayer2 = {0x0E6B01D1,0xD407,0x4C85,{0xBF,0x5F,0x1C,0x01,0xF6,0x15,0x02,0x80}};
+const IID IID_IWMPCore2 = {0xBC17E5B7,0x7561,0x4C18,{0xBB,0x90,0x17,0xD4,0x85,0x77,0x56,0x59}};
+const IID IID_IWMPCore3 = {0x7587C667,0x628F,0x499F,{0x88,0xE7,0x6A,0x6F,0x4E,0x88,0x84,0x64}};
+const IID IID_IWMPNetwork = {0xEC21B779,0xEDEF,0x462D,{0xBB,0xA4,0xAD,0x9D,0xDE,0x2B,0x29,0xA7}};
+
+enum WMPOpenState
+{
+    wmposUndefined  = 0,
+    wmposPlaylistChanging   = 1,
+    wmposPlaylistLocating   = 2,
+    wmposPlaylistConnecting = 3,
+    wmposPlaylistLoading    = 4,
+    wmposPlaylistOpening    = 5,
+    wmposPlaylistOpenNoMedia    = 6,
+    wmposPlaylistChanged    = 7,
+    wmposMediaChanging  = 8,
+    wmposMediaLocating  = 9,
+    wmposMediaConnecting    = 10,
+    wmposMediaLoading   = 11,
+    wmposMediaOpening   = 12,
+    wmposMediaOpen  = 13,
+    wmposBeginCodecAcquisition  = 14,
+    wmposEndCodecAcquisition    = 15,
+    wmposBeginLicenseAcquisition    = 16,
+    wmposEndLicenseAcquisition  = 17,
+    wmposBeginIndividualization = 18,
+    wmposEndIndividualization   = 19,
+    wmposMediaWaiting   = 20,
+    wmposOpeningUnknownURL  = 21
+};
+
+enum WMPPlayState
+{
+    wmppsUndefined  = 0,
+    wmppsStopped    = 1,
+    wmppsPaused = 2,
+    wmppsPlaying    = 3,
+    wmppsScanForward    = 4,
+    wmppsScanReverse    = 5,
+    wmppsBuffering  = 6,
+    wmppsWaiting    = 7,
+    wmppsMediaEnded = 8,
+    wmppsTransitioning  = 9,
+    wmppsReady  = 10,
+    wmppsReconnecting   = 11,
+    wmppsLast   = 12
+};
+
+
+struct IWMPMedia : public IDispatch
+{
+public:
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_isIdentical(
+        /* [in] */ IWMPMedia __RPC_FAR *pIWMPMedia,
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pvbool) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_sourceURL(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrSourceURL) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_name(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrName) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_name(
+        /* [in] */ BSTR pbstrName) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_imageSourceWidth(
+        /* [retval][out] */ long __RPC_FAR *pWidth) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_imageSourceHeight(
+        /* [retval][out] */ long __RPC_FAR *pHeight) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_markerCount(
+        /* [retval][out] */ long __RPC_FAR *pMarkerCount) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getMarkerTime(
+        /* [in] */ long MarkerNum,
+        /* [retval][out] */ double __RPC_FAR *pMarkerTime) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getMarkerName(
+        /* [in] */ long MarkerNum,
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrMarkerName) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_duration(
+        /* [retval][out] */ double __RPC_FAR *pDuration) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_durationString(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrDuration) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_attributeCount(
+        /* [retval][out] */ long __RPC_FAR *plCount) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getAttributeName(
+        /* [in] */ long lIndex,
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrItemName) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getItemInfo(
+        /* [in] */ BSTR bstrItemName,
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrVal) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setItemInfo(
+        /* [in] */ BSTR bstrItemName,
+        /* [in] */ BSTR bstrVal) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getItemInfoByAtom(
+        /* [in] */ long lAtom,
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrVal) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE isMemberOf(
+        /* [in] */ IUnknown __RPC_FAR *pPlaylist,
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pvarfIsMemberOf) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE isReadOnlyItem(
+        /* [in] */ BSTR bstrItemName,
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pvarfIsReadOnly) = 0;
+
+};
+
+struct IWMPControls : public IDispatch
+{
+public:
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_isAvailable(
+        /* [in] */ BSTR bstrItem,
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pIsAvailable) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE play( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE stop( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE pause( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE fastForward( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE fastReverse( void) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentPosition(
+        /* [retval][out] */ double __RPC_FAR *pdCurrentPosition) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_currentPosition(
+        /* [in] */ double pdCurrentPosition) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentPositionString(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrCurrentPosition) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE next( void) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE previous( void) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentItem(
+        /* [retval][out] */ IWMPMedia __RPC_FAR *__RPC_FAR *ppIWMPMedia) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_currentItem(
+        /* [in] */ IWMPMedia __RPC_FAR *ppIWMPMedia) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentMarker(
+        /* [retval][out] */ long __RPC_FAR *plMarker) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_currentMarker(
+        /* [in] */ long plMarker) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE playItem(
+        /* [in] */ IWMPMedia __RPC_FAR *pIWMPMedia) = 0;
+
+};
+
+
+struct IWMPSettings : public IDispatch
+{
+public:
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_isAvailable(
+        /* [in] */ BSTR bstrItem,
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pIsAvailable) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_autoStart(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfAutoStart) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_autoStart(
+        /* [in] */ VARIANT_BOOL pfAutoStart) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_baseURL(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrBaseURL) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_baseURL(
+        /* [in] */ BSTR pbstrBaseURL) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_defaultFrame(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrDefaultFrame) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_defaultFrame(
+        /* [in] */ BSTR pbstrDefaultFrame) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_invokeURLs(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfInvokeURLs) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_invokeURLs(
+        /* [in] */ VARIANT_BOOL pfInvokeURLs) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_mute(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfMute) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_mute(
+        /* [in] */ VARIANT_BOOL pfMute) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_playCount(
+        /* [retval][out] */ long __RPC_FAR *plCount) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_playCount(
+        /* [in] */ long plCount) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_rate(
+        /* [retval][out] */ double __RPC_FAR *pdRate) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_rate(
+        /* [in] */ double pdRate) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_balance(
+        /* [retval][out] */ long __RPC_FAR *plBalance) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_balance(
+        /* [in] */ long plBalance) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_volume(
+        /* [retval][out] */ long __RPC_FAR *plVolume) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_volume(
+        /* [in] */ long plVolume) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getMode(
+        /* [in] */ BSTR bstrMode,
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pvarfMode) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setMode(
+        /* [in] */ BSTR bstrMode,
+        /* [in] */ VARIANT_BOOL varfMode) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_enableErrorDialogs(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfEnableErrorDialogs) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_enableErrorDialogs(
+        /* [in] */ VARIANT_BOOL pfEnableErrorDialogs) = 0;
+
+};
+
+struct IWMPNetwork : public IDispatch
+{
+public:
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_bandWidth(
+        /* [retval][out] */ long __RPC_FAR *plBandwidth) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_recoveredPackets(
+        /* [retval][out] */ long __RPC_FAR *plRecoveredPackets) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_sourceProtocol(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrSourceProtocol) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_receivedPackets(
+        /* [retval][out] */ long __RPC_FAR *plReceivedPackets) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_lostPackets(
+        /* [retval][out] */ long __RPC_FAR *plLostPackets) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_receptionQuality(
+        /* [retval][out] */ long __RPC_FAR *plReceptionQuality) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_bufferingCount(
+        /* [retval][out] */ long __RPC_FAR *plBufferingCount) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_bufferingProgress(
+        /* [retval][out] */ long __RPC_FAR *plBufferingProgress) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_bufferingTime(
+        /* [retval][out] */ long __RPC_FAR *plBufferingTime) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_bufferingTime(
+        /* [in] */ long plBufferingTime) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_frameRate(
+        /* [retval][out] */ long __RPC_FAR *plFrameRate) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_maxBitRate(
+        /* [retval][out] */ long __RPC_FAR *plBitRate) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_bitRate(
+        /* [retval][out] */ long __RPC_FAR *plBitRate) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getProxySettings(
+        /* [in] */ BSTR bstrProtocol,
+        /* [retval][out] */ long __RPC_FAR *plProxySetting) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setProxySettings(
+        /* [in] */ BSTR bstrProtocol,
+        /* [in] */ long lProxySetting) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getProxyName(
+        /* [in] */ BSTR bstrProtocol,
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrProxyName) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setProxyName(
+        /* [in] */ BSTR bstrProtocol,
+        /* [in] */ BSTR bstrProxyName) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getProxyPort(
+        /* [in] */ BSTR bstrProtocol,
+        /* [retval][out] */ long __RPC_FAR *lProxyPort) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setProxyPort(
+        /* [in] */ BSTR bstrProtocol,
+        /* [in] */ long lProxyPort) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getProxyExceptionList(
+        /* [in] */ BSTR bstrProtocol,
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrExceptionList) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setProxyExceptionList(
+        /* [in] */ BSTR bstrProtocol,
+        /* [in] */ BSTR pbstrExceptionList) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE getProxyBypassForLocal(
+        /* [in] */ BSTR bstrProtocol,
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfBypassForLocal) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE setProxyBypassForLocal(
+        /* [in] */ BSTR bstrProtocol,
+        /* [in] */ VARIANT_BOOL fBypassForLocal) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_maxBandwidth(
+        /* [retval][out] */ long __RPC_FAR *lMaxBandwidth) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_maxBandwidth(
+        /* [in] */ long lMaxBandwidth) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_downloadProgress(
+        /* [retval][out] */ long __RPC_FAR *plDownloadProgress) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_encodedFrameRate(
+        /* [retval][out] */ long __RPC_FAR *plFrameRate) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_framesSkipped(
+        /* [retval][out] */ long __RPC_FAR *plFrames) = 0;
+
+};
+
+struct IWMPCore : public IDispatch
+{
+public:
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE close( void) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_URL(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrURL) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_URL(
+        /* [in] */ BSTR pbstrURL) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_openState(
+        /* [retval][out] */ WMPOpenState __RPC_FAR *pwmpos) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_playState(
+        /* [retval][out] */ WMPPlayState __RPC_FAR *pwmpps) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_controls(
+        /* [retval][out] */ IWMPControls __RPC_FAR *__RPC_FAR *ppControl) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_settings(
+        /* [retval][out] */ IWMPSettings __RPC_FAR *__RPC_FAR *ppSettings) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentMedia(
+        /* [retval][out] */ IWMPMedia __RPC_FAR *__RPC_FAR *ppMedia) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_currentMedia(
+        /* [in] */ IUnknown __RPC_FAR *ppMedia) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_mediaCollection(
+        /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppMediaCollection) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_playlistCollection(
+        /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppPlaylistCollection) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_versionInfo(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrVersionInfo) = 0;
+
+    virtual /* [id] */ HRESULT STDMETHODCALLTYPE launchURL(
+        /* [in] */ BSTR bstrURL) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_network(
+        /* [retval][out] */ IWMPNetwork __RPC_FAR *__RPC_FAR *ppQNI) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_currentPlaylist(
+        /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppPL) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_currentPlaylist(
+        /* [in] */ IUnknown __RPC_FAR *ppPL) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_cdromCollection(
+        /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppCdromCollection) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_closedCaption(
+        /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppClosedCaption) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_isOnline(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pfOnline) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Error(
+        /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppError) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_status(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrStatus) = 0;
+
+};
+
+struct IWMPCore2 : public IWMPCore
+{
+public:
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_dvd(
+        /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppDVD) = 0;
+
+};
+
+struct IWMPCore3 : public IWMPCore2
+{
+public:
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE newPlaylist(
+        /* [in] */ BSTR bstrName,
+        /* [in] */ BSTR bstrURL,
+        /* [retval][out] */ IUnknown __RPC_FAR *__RPC_FAR *ppPlaylist) = 0;
+
+    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE newMedia(
+        /* [in] */ BSTR bstrURL,
+        /* [retval][out] */ IWMPMedia __RPC_FAR *__RPC_FAR *ppMedia) = 0;
+
+};
+
+#ifdef WXTEST_ATL
+    MIDL_INTERFACE("6BF52A4F-394A-11D3-B153-00C04F79FAA6")
+#else
+    struct
+#endif
+IWMPPlayer : public IWMPCore
+{
+public:
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_enabled(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnabled) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_enabled(
+        /* [in] */ VARIANT_BOOL pbEnabled) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_fullScreen(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbFullScreen) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_fullScreen(
+        VARIANT_BOOL pbFullScreen) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_enableContextMenu(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnableContextMenu) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_enableContextMenu(
+        VARIANT_BOOL pbEnableContextMenu) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_uiMode(
+        /* [in] */ BSTR pbstrMode) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_uiMode(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrMode) = 0;
+};
+
+struct IWMPPlayer2 : public IWMPCore
+{
+public:
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_enabled(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnabled) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_enabled(
+        /* [in] */ VARIANT_BOOL pbEnabled) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_fullScreen(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbFullScreen) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_fullScreen(
+        VARIANT_BOOL pbFullScreen) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_enableContextMenu(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnableContextMenu) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_enableContextMenu(
+        VARIANT_BOOL pbEnableContextMenu) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_uiMode(
+        /* [in] */ BSTR pbstrMode) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_uiMode(
+        /* [retval][out] */ BSTR __RPC_FAR *pbstrMode) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_stretchToFit(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnabled) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_stretchToFit(
+        /* [in] */ VARIANT_BOOL pbEnabled) = 0;
+
+    virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_windowlessVideo(
+        /* [retval][out] */ VARIANT_BOOL __RPC_FAR *pbEnabled) = 0;
+
+    virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_windowlessVideo(
+        /* [in] */ VARIANT_BOOL pbEnabled) = 0;
+
+};
+
+//---------------------------------------------------------------------------
+//
+//  wxWMP10MediaBackend
+//
+//---------------------------------------------------------------------------
+
+class WXDLLIMPEXP_MEDIA wxWMP10MediaBackend : public wxMediaBackendCommonBase
+{
+public:
+    wxWMP10MediaBackend();
+    virtual ~wxWMP10MediaBackend();
+
+    virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
+                                     wxWindowID id,
+                                     const wxPoint& pos,
+                                     const wxSize& size,
+                                     long style,
+                                     const wxValidator& validator,
+                                     const wxString& name);
+
+    virtual bool Play();
+    virtual bool Pause();
+    virtual bool Stop();
+
+    virtual bool Load(const wxString& fileName);
+    virtual bool Load(const wxURI& location);
+    virtual bool Load(const wxURI& location, const wxURI& proxy);
+
+    bool DoLoad(const wxString& location);
+    void FinishLoad();
+
+    virtual wxMediaState GetState();
+
+    virtual bool SetPosition(wxLongLong where);
+    virtual wxLongLong GetPosition();
+    virtual wxLongLong GetDuration();
+
+    virtual void Move(int x, int y, int w, int h);
+    wxSize GetVideoSize() const;
+
+    virtual double GetPlaybackRate();
+    virtual bool SetPlaybackRate(double);
+
+    virtual double GetVolume();
+    virtual bool SetVolume(double);
+
+    virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
+
+    virtual wxLongLong GetDownloadProgress();
+    virtual wxLongLong GetDownloadTotal();
+
+
+#ifdef WXTEST_ATL
+        CAxWindow  m_wndView;
+#else
+        wxActiveXContainer* m_pAX;
+#endif
+    IWMPPlayer* m_pWMPPlayer;       // Main activex interface
+    IWMPSettings* m_pWMPSettings;   // Settings such as volume
+    IWMPControls* m_pWMPControls;   // Control interface (play etc.)
+    wxSize m_bestSize;              // Actual movie size
+
+    bool m_bWasStateChanged;        // See the "introduction"
+
+    friend class wxWMP10MediaEvtHandler;
+    DECLARE_DYNAMIC_CLASS(wxWMP10MediaBackend)
+};
+
+#ifndef WXTEST_ATL
+class WXDLLIMPEXP_MEDIA wxWMP10MediaEvtHandler : public wxEvtHandler
+{
+public:
+    wxWMP10MediaEvtHandler(wxWMP10MediaBackend *amb) :
+       m_amb(amb)
+    {
+        m_amb->m_pAX->Connect(m_amb->m_pAX->GetId(),
+            wxEVT_ACTIVEX,
+            wxActiveXEventHandler(wxWMP10MediaEvtHandler::OnActiveX),
+            NULL, this
+                              );
+    }
+
+    void OnActiveX(wxActiveXEvent& event);
+
+private:
+    wxWMP10MediaBackend *m_amb;
+
+    DECLARE_NO_COPY_CLASS(wxWMP10MediaEvtHandler)
+};
+#endif
+
+//===========================================================================
+//  IMPLEMENTATION
+//===========================================================================
+
+//---------------------------------------------------------------------------
+//
+// wxWMP10MediaBackend
+//
+//---------------------------------------------------------------------------
+
+IMPLEMENT_DYNAMIC_CLASS(wxWMP10MediaBackend, wxMediaBackend)
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend Constructor
+//---------------------------------------------------------------------------
+wxWMP10MediaBackend::wxWMP10MediaBackend()
+                 :
+#ifndef WXTEST_ATL
+                m_pAX(NULL),
+#endif
+                m_pWMPPlayer(NULL)
+
+{
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend Destructor
+//---------------------------------------------------------------------------
+wxWMP10MediaBackend::~wxWMP10MediaBackend()
+{
+    if(m_pWMPPlayer)
+    {
+#ifndef WXTEST_ATL
+        m_pAX->DissociateHandle();
+        delete m_pAX;
+
+        m_ctrl->PopEventHandler(true);
+#else
+        AtlAxWinTerm();
+        _Module.Term();
+#endif
+
+        m_pWMPPlayer->Release();
+        m_pWMPSettings->Release();
+        m_pWMPControls->Release();
+    }
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::CreateControl
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
+                                     wxWindowID id,
+                                     const wxPoint& pos,
+                                     const wxSize& size,
+                                     long style,
+                                     const wxValidator& validator,
+                                     const wxString& name)
+{
+#ifndef WXTEST_ATL
+    if( ::CoCreateInstance(CLSID_WMP10, NULL,
+                                  CLSCTX_INPROC_SERVER,
+                                  IID_IWMPPlayer, (void**)&m_pWMPPlayer) != 0 )
+    {
+        if( ::CoCreateInstance(CLSID_WMP10ALT, NULL,
+                                  CLSCTX_INPROC_SERVER,
+                                  IID_IWMPPlayer, (void**)&m_pWMPPlayer) != 0 )
+            return false;
+
+        if( m_pWMPPlayer->get_settings(&m_pWMPSettings) != 0)
+        {
+            m_pWMPPlayer->Release();
+            wxLogSysError(wxT("Could not obtain settings from WMP10!"));
+            return false;
+        }
+
+        if( m_pWMPPlayer->get_controls(&m_pWMPControls) != 0)
+        {
+            m_pWMPSettings->Release();
+            m_pWMPPlayer->Release();
+            wxLogSysError(wxT("Could not obtain controls from WMP10!"));
+            return false;
+        }
+    }
+#endif
+
+    //
+    // Create window
+    // By default wxWindow(s) is created with a border -
+    // so we need to get rid of those
+    //
+    // Since we don't have a child window like most other
+    // backends, we don't need wxCLIP_CHILDREN
+    //
+    if ( !ctrl->wxControl::Create(parent, id, pos, size,
+                            (style & ~wxBORDER_MASK) | wxBORDER_NONE,
+                            validator, name) )
+        return false;
+
+    //
+    // Now create the ActiveX container along with the media player
+    // interface and query them
+    //
+    m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
+
+#ifndef WXTEST_ATL
+    m_pAX = new wxActiveXContainer(ctrl, IID_IWMPPlayer, m_pWMPPlayer);
+
+    // Connect for events
+    m_ctrl->PushEventHandler(new wxWMP10MediaEvtHandler(this));
+#else
+    _Module.Init(NULL, ::GetModuleHandle(NULL));
+    AtlAxWinInit();
+    CComPtr<IAxWinHostWindow>  spHost;
+
+    HRESULT hr;
+    RECT rcClient;
+    ::GetClientRect((HWND)ctrl->GetHandle(), &rcClient);
+    m_wndView.Create((HWND)ctrl->GetHandle(), rcClient, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
+    hr = m_wndView.QueryHost(&spHost);
+    hr = spHost->CreateControl(CComBSTR(_T("{6BF52A52-394A-11d3-B153-00C04F79FAA6}")), m_wndView, 0);
+    hr = m_wndView.QueryControl(&m_pWMPPlayer);
+
+    if( m_pWMPPlayer->get_settings(&m_pWMPSettings) != 0)
+    {
+        m_pWMPPlayer->Release();
+        wxLogSysError(wxT("Could not obtain settings from WMP10!"));
+        return false;
+    }
+
+    if( m_pWMPPlayer->get_controls(&m_pWMPControls) != 0)
+    {
+        m_pWMPSettings->Release();
+        m_pWMPPlayer->Release();
+        wxLogSysError(wxT("Could not obtain controls from WMP10!"));
+        return false;
+    }
+#endif
+
+    //
+    //  Here we set up wx-specific stuff for the default
+    //  settings wxMediaCtrl says it will stay to
+    //
+
+    IWMPPlayer2* pWMPPlayer2; // Only 2 has windowless video and stretchtofit
+    if(m_pWMPPlayer->QueryInterface(IID_IWMPPlayer2, (void**)&pWMPPlayer2) == 0)
+    {
+        // We don't check errors here as these arn't particularily important
+        // and may not be implemented (i.e. stretchToFit on CE)
+        pWMPPlayer2->put_windowlessVideo(VARIANT_TRUE);
+        pWMPPlayer2->put_stretchToFit(VARIANT_TRUE);
+        pWMPPlayer2->Release();
+    }
+
+    // by default true (see the "introduction")
+    m_pWMPSettings->put_autoStart(VARIANT_TRUE);
+    // by default enabled
+    wxWMP10MediaBackend::ShowPlayerControls(wxMEDIACTRLPLAYERCONTROLS_NONE);
+    // by default with AM only 0.5
+    wxWMP10MediaBackend::SetVolume(1.0);
+
+    // don't erase the background of our control window so that resizing is a
+    // bit smoother
+    m_ctrl->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
+
+    // success
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::Load (file version)
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::Load(const wxString& fileName)
+{
+    return DoLoad(fileName);
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::Load (URL Version)
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::Load(const wxURI& location)
+{
+    return DoLoad(location.BuildURI());
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::Load (URL Version with Proxy)
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::Load(const wxURI& location,
+                               const wxURI& proxy)
+{
+    bool bOK = false;
+
+    IWMPNetwork* pWMPNetwork;
+    if( m_pWMPPlayer->get_network(&pWMPNetwork) == 0 )
+    {
+        long lOldSetting;
+        if( pWMPNetwork->getProxySettings(
+                    wxBasicString(location.GetScheme()).Get(), &lOldSetting
+                                        ) == 0 &&
+
+            pWMPNetwork->setProxySettings(
+                    wxBasicString(location.GetScheme()).Get(), // protocol
+                                2) == 0) // 2 == manually specify
+        {
+            BSTR bsOldName = NULL;
+            long lOldPort = 0;
+
+            pWMPNetwork->getProxyName(
+                        wxBasicString(location.GetScheme()).Get(),
+                        &bsOldName);
+            pWMPNetwork->getProxyPort(
+                        wxBasicString(location.GetScheme()).Get(),
+                        &lOldPort);
+
+            long lPort;
+            wxString server;
+            if(proxy.IsReference())
+            {
+                server = proxy.GetScheme();
+                lPort = wxAtoi(proxy.GetPath());
+            }
+            else
+            {
+                server = proxy.GetServer();
+                lPort = wxAtoi(proxy.GetPort());
+            }
+
+            if( pWMPNetwork->setProxyName(
+                        wxBasicString(location.GetScheme()).Get(), // proto
+                        wxBasicString(server).Get() ) == 0  &&
+
+                pWMPNetwork->setProxyPort(
+                        wxBasicString(location.GetScheme()).Get(), // proto
+                        lPort
+                                         ) == 0
+              )
+            {
+                bOK = DoLoad(location.BuildURI());
+
+                pWMPNetwork->setProxySettings(
+                    wxBasicString(location.GetScheme()).Get(), // protocol
+                                lOldSetting);
+                if(bsOldName)
+                    pWMPNetwork->setProxyName(
+                        wxBasicString(location.GetScheme()).Get(), // protocol
+                                    bsOldName);
+
+                if(lOldPort)
+                    pWMPNetwork->setProxyPort(
+                        wxBasicString(location.GetScheme()).Get(), // protocol
+                                lOldPort);
+
+                pWMPNetwork->Release();
+            }
+            else
+                pWMPNetwork->Release();
+
+        }
+        else
+            pWMPNetwork->Release();
+
+    }
+
+    return bOK;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::DoLoad
+//
+// Called by all functions - this actually renders
+// the file and sets up the filter graph
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::DoLoad(const wxString& location)
+{
+    HRESULT hr;
+
+#if 0 // See the "introduction" - this is the duration hack
+    // ------------------ BLATENT HACK ALERT -------------------------
+    // Normally we can only get the duration of things already in an
+    // existing playlist or playing - however this clever "workaround"
+    // enables us to get the duration even when stopped :)
+    // http://weblogs.asp.net/rweigelt/archive/2003/07/02/9613.aspx
+
+    IWMPCore3* pWMPCore3;
+    double outDuration;
+    if(m_pWMPPlayer->QueryInterface(IID_IWMPCore3, (void**) &pWMPCore3) == 0)
+    {
+        IWMPMedia* pWMPMedia;
+
+        if( (hr = pWMPCore3->newMedia(wxBasicString(location).Get(),
+                               &pWMPMedia)) == 0)
+        {
+            // this (get_duration) will actually FAIL, but it will work.
+            pWMPMedia->get_duration(&outDuration);
+            pWMPCore3->put_currentMedia(pWMPMedia);
+            pWMPMedia->Release();
+        }
+
+        pWMPCore3->Release();
+    }
+    else
+#endif
+    {
+        // just load it the "normal" way
+        hr = m_pWMPPlayer->put_URL( wxBasicString(location).Get() );
+    }
+
+    if(FAILED(hr))
+    {
+        wxWMP10LOG(hr);
+        return false;
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::FinishLoad
+//
+// Called when our media is about to play (a.k.a. wmposMediaOpen)
+//---------------------------------------------------------------------------
+void wxWMP10MediaBackend::FinishLoad()
+{
+    // Get the original video size
+    // THIS WILL NOT WORK UNLESS THE MEDIA IS ABOUT TO PLAY
+    // See the "introduction" - also get_currentMedia will return
+    // "1" which is a VALID HRESULT value
+    // and a NULL pWMPMedia if the media isn't the "current" one
+    // which is rather unintuitive in the sense that it uses it
+    // (i.e. basically not currently playing)...
+    IWMPMedia* pWMPMedia;
+    if(m_pWMPPlayer->get_currentMedia(&pWMPMedia) == 0)
+    {
+        pWMPMedia->get_imageSourceWidth((long*)&m_bestSize.x);
+        pWMPMedia->get_imageSourceHeight((long*)&m_bestSize.y);
+        pWMPMedia->Release();
+    }
+    else
+    {
+        wxLogDebug(wxT("Could not get media"));
+    }
+
+    NotifyMovieLoaded();
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::ShowPlayerControls
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
+{
+    if(!flags)
+    {
+        m_pWMPPlayer->put_enabled(VARIANT_FALSE);
+        m_pWMPPlayer->put_uiMode(wxBasicString(wxT("none")).Get());
+    }
+    else
+    {
+        // TODO: use "custom"? (note that CE only supports none/full)
+        m_pWMPPlayer->put_uiMode(wxBasicString(wxT("full")).Get());
+        m_pWMPPlayer->put_enabled(VARIANT_TRUE);
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::Play
+//
+// Plays the stream.  If it is non-seekable, it will restart it (implicit).
+//
+// TODO: We use SUCCEEDED due to pickiness on IMediaPlayer are doing it here
+// but do we need to?
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::Play()
+{
+    // Actually try to play the movie (will fail if not loaded completely)
+    HRESULT hr = m_pWMPControls->play();
+    if(SUCCEEDED(hr))
+    {
+       m_bWasStateChanged = true;
+       return true;
+    }
+    wxWMP10LOG(hr);
+    return false;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::Pause
+//
+// Pauses the stream.
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::Pause()
+{
+    HRESULT hr = m_pWMPControls->pause();
+    if(SUCCEEDED(hr))
+    {
+        m_bWasStateChanged = true;
+        return true;
+    }
+    wxWMP10LOG(hr);
+    return false;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::Stop
+//
+// Stops the stream.
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::Stop()
+{
+    HRESULT hr = m_pWMPControls->stop();
+    if(SUCCEEDED(hr))
+    {
+        // Seek to beginning
+        wxWMP10MediaBackend::SetPosition(0);
+        m_bWasStateChanged = true;
+        return true;
+    }
+    wxWMP10LOG(hr);
+    return false;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::SetPosition
+//
+// WMP10 position values are a double in seconds - we just translate
+// to our base here
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::SetPosition(wxLongLong where)
+{
+    HRESULT hr = m_pWMPControls->put_currentPosition(
+                        ((LONGLONG)where.GetValue()) / 1000.0
+                                     );
+    if(FAILED(hr))
+    {
+        wxWMP10LOG(hr);
+        return false;
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::GetPosition
+//
+// WMP10 position values are a double in seconds - we just translate
+// to our base here
+//---------------------------------------------------------------------------
+wxLongLong wxWMP10MediaBackend::GetPosition()
+{
+    double outCur;
+    HRESULT hr = m_pWMPControls->get_currentPosition(&outCur);
+    if(FAILED(hr))
+    {
+        wxWMP10LOG(hr);
+        return 0;
+    }
+
+    // h,m,s,milli - outCur is in 1 second (double)
+    outCur *= 1000;
+    wxLongLong ll;
+    ll.Assign(outCur);
+
+    return ll;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::GetVolume
+//
+// Volume 0-100
+//---------------------------------------------------------------------------
+double wxWMP10MediaBackend::GetVolume()
+{
+    long lVolume;
+    HRESULT hr = m_pWMPSettings->get_volume(&lVolume);
+    if(FAILED(hr))
+    {
+        wxWMP10LOG(hr);
+        return 0.0;
+    }
+
+    return (double)lVolume / 100.0;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::SetVolume
+//
+// Volume 0-100
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::SetVolume(double dVolume)
+{
+    HRESULT hr = m_pWMPSettings->put_volume( (long) (dVolume * 100.0) );
+    if(FAILED(hr))
+    {
+        wxWMP10LOG(hr);
+        return false;
+    }
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::GetDuration
+//
+// Obtains the duration of the media.
+//
+// See the "introduction"
+//
+// The good news is that this doesn't appear to have the XING header
+// parser problem that WMP6 SDK/IActiveMovie/IMediaPlayer/IWMP has
+//---------------------------------------------------------------------------
+wxLongLong wxWMP10MediaBackend::GetDuration()
+{
+    double outDuration = 0.0;
+
+    IWMPMedia* pWMPMedia;
+    if(m_pWMPPlayer->get_currentMedia(&pWMPMedia) == 0)
+    {
+        if(pWMPMedia->get_duration(&outDuration) != 0)
+        {
+            wxLogDebug(wxT("get_duration failed"));
+        }
+        pWMPMedia->Release();
+    }
+
+
+    // h,m,s,milli - outDuration is in 1 second (double)
+    outDuration *= 1000;
+    wxLongLong ll;
+    ll.Assign(outDuration);
+
+    return ll;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::GetState
+//
+// Returns the current state
+//---------------------------------------------------------------------------
+wxMediaState wxWMP10MediaBackend::GetState()
+{
+    WMPPlayState nState;
+    HRESULT hr = m_pWMPPlayer->get_playState(&nState);
+    if(FAILED(hr))
+    {
+        wxWMP10LOG(hr);
+        return wxMEDIASTATE_STOPPED;
+    }
+
+    switch(nState)
+    {
+    case wmppsPaused:
+        return wxMEDIASTATE_PAUSED;
+    case wmppsPlaying:
+        return wxMEDIASTATE_PLAYING;
+    default:
+        return wxMEDIASTATE_STOPPED;
+    }
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::GetPlaybackRate
+//
+// Just get the rate from WMP10
+//---------------------------------------------------------------------------
+double wxWMP10MediaBackend::GetPlaybackRate()
+{
+    double dRate;
+    HRESULT hr = m_pWMPSettings->get_rate(&dRate);
+    if(FAILED(hr))
+    {
+        wxWMP10LOG(hr);
+        return 0.0;
+    }
+    return dRate;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::SetPlaybackRate
+//
+// Sets the playback rate of the media - DirectShow is pretty good
+// about this, actually
+//---------------------------------------------------------------------------
+bool wxWMP10MediaBackend::SetPlaybackRate(double dRate)
+{
+    HRESULT hr = m_pWMPSettings->put_rate(dRate);
+    if(FAILED(hr))
+    {
+        wxWMP10LOG(hr);
+        return false;
+    }
+
+    return true;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::GetVideoSize
+//
+// Obtains the cached original video size
+//---------------------------------------------------------------------------
+wxSize wxWMP10MediaBackend::GetVideoSize() const
+{
+    return m_bestSize;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::Move
+//
+// We take care of this in our redrawing
+//---------------------------------------------------------------------------
+void wxWMP10MediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
+#ifdef WXTEST_ATL
+                            int w, int h
+#else
+                            int WXUNUSED(w), int WXUNUSED(h)
+#endif
+                            )
+{
+#ifdef WXTEST_ATL
+    m_wndView.MoveWindow(0,0,w,h);
+#endif
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::GetDownloadProgress()
+//---------------------------------------------------------------------------
+wxLongLong wxWMP10MediaBackend::GetDownloadProgress()
+{
+    IWMPNetwork* pWMPNetwork;
+    if( m_pWMPPlayer->get_network(&pWMPNetwork) == 0 )
+    {
+        long lPercentProg;
+        if(pWMPNetwork->get_downloadProgress(&lPercentProg) == 0)
+        {
+            pWMPNetwork->Release();
+            return (GetDownloadTotal() * lPercentProg) / 100;
+        }
+        pWMPNetwork->Release();
+    }
+    return 0;
+}
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::GetDownloadTotal()
+//---------------------------------------------------------------------------
+wxLongLong wxWMP10MediaBackend::GetDownloadTotal()
+{
+    IWMPMedia* pWMPMedia;
+    if(m_pWMPPlayer->get_currentMedia(&pWMPMedia) == 0)
+    {
+        BSTR bsOut;
+        pWMPMedia->getItemInfo(wxBasicString(wxT("FileSize")).Get(),
+                               &bsOut);
+
+        wxString sFileSize = wxConvertStringFromOle(bsOut);
+        long lFS;
+        sFileSize.ToLong(&lFS);
+        pWMPMedia->Release();
+        return lFS;
+    }
+
+    return 0;
+}
+
+
+//---------------------------------------------------------------------------
+// wxWMP10MediaBackend::OnActiveX
+//
+// Handle events sent from our activex control (_WMPOCXEvents actually).
+//
+// The weird numbers in the switch statement here are "dispatch ids"
+// (the numbers in the id field like ( id(xxx) ) ) from amcompat.idl
+// and wmp.IDL.
+//---------------------------------------------------------------------------
+#ifndef WXTEST_ATL
+void wxWMP10MediaEvtHandler::OnActiveX(wxActiveXEvent& event)
+{
+    switch(event.GetDispatchId())
+    {
+    case 0x000013ed: // playstatechange
+        if(event.ParamCount() >= 1)
+        {
+            switch (event[0].GetInteger())
+            {
+            case wmppsMediaEnded: // media ended
+                if ( m_amb->SendStopEvent() )
+                {
+                    // NB: If we do Stop() or similar here the media
+                    // actually starts over and plays a bit before
+                    // stopping. It stops by default, however, so
+                    // there is no real need to do anything here...
+
+                    // send the event to our child
+                    m_amb->QueueFinishEvent();
+                }
+                break;
+
+            case wmppsStopped: // stopping
+                m_amb->QueueStopEvent();
+                break;
+            case wmppsPaused: // pause
+                m_amb->QueuePauseEvent();
+                break;
+            case wmppsPlaying: // play
+                m_amb->QueuePlayEvent();
+                break;
+            default:
+                break;
+            }
+        }
+        else
+            event.Skip();
+        break;
+
+    case 0x00001389: // openstatechange
+        if(event.ParamCount() >= 1)
+        {
+            int nState = event[0].GetInteger();
+            if(nState == wmposMediaOpen)
+            {
+                // See the "introduction"
+                m_amb->m_bWasStateChanged = false;
+                m_amb->FinishLoad();
+                if(!m_amb->m_bWasStateChanged)
+                    m_amb->Stop();
+            }
+        }
+        else
+            event.Skip();
+        break;
+
+    case 0x0000196e: // mousedown
+        m_amb->m_ctrl->SetFocus();
+        break;
+
+    default:
+        event.Skip();
+        return;
+    }
+}
+
+#endif
+// in source file that contains stuff you don't directly use
+#include "wx/html/forcelnk.h"
+FORCE_LINK_ME(wxmediabackend_wmp10)
+
+#if 0 // Windows Media Player Mobile 9 hacks
+
+//------------------WMP Mobile 9 hacks-----------------------------------
+// It was mentioned in the introduction that while there was no official
+// programming interface on WMP mobile 9
+// (SmartPhone/Pocket PC 2003 emulator etc.)
+// there were some windows message hacks that are able to get
+// you playing a file through WMP.
+//
+// Here are those hacks. They do indeed "work" as expected - just call
+// SendMessage with one of those myterious values layed out in
+// Peter Foot's Friday, May 21, 2004 Blog Post on the issue.
+// (He says they are in a registery section entitled "Pendant Bus")
+//
+// How do you play a certain file? Simply calling "start [file]" or
+// wxWinCEExecute([file]) should do the trick
+
+bool wxWinCEExecute(const wxString& path, int nShowStyle = SW_SHOWNORMAL)
+{
+    WinStruct<SHELLEXECUTEINFO> sei;
+    sei.lpFile = path.c_str();
+    sei.lpVerb = _T("open");
+    sei.nShow = nShowStyle;
+
+    ::ShellExecuteEx(&sei);
+
+    return ((int) sei.hInstApp) > 32;
+}
+
+bool MyApp::OnInit()
+{
+    HWND hwnd = ::FindWindow(TEXT("WMP for Mobile Devices"), TEXT("Windows Media"));
+    if(!hwnd)
+    {
+        if( wxWinCEExecute(wxT("\\Windows\\wmplayer.exe"), SW_MINIMIZE) )
+        {
+            hwnd = ::FindWindow(TEXT("WMP for Mobile Devices"), TEXT("Windows Media"));
+        }
+    }
+
+    if(hwnd)
+    {
+        // hide wmp window
+        ::SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0,
+                       SWP_NOMOVE|SWP_NOSIZE|SWP_HIDEWINDOW);
+
+        // Stop         == 32970
+        // Prev Track   == 32971
+        // Next Track   == 32972
+        // Shuffle      == 32973
+        // Repeat       == 32974
+        // Vol Up       == 32975
+        // Vol Down     == 32976
+        // Play         == 32978
+        ::SendMessage(hwnd, 32978, NULL, 0);
+    }
+}
+
+#endif // WMP mobile 9 hacks
+
+//---------------------------------------------------------------------------
+//  End wxMediaCtrl Compilation Guard and this file
+//---------------------------------------------------------------------------
+#endif // wxUSE_MEDIACTRL
index 5b086b77db530ee1bf65b30e272958fd5c2ec209..d3bcdd62719924cb7b413869fd84ef552307f6ae 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
-// Name:        src/msw/ole/activex.cpp
+// Name:        msw/ole/activex.cpp
 // Purpose:     wxActiveXContainer implementation
 // Author:      Ryan Norton <wxprojects@comcast.net>, Lindsay Mathieson <???>
 // Modified by:
 // Purpose:     wxActiveXContainer implementation
 // Author:      Ryan Norton <wxprojects@comcast.net>, Lindsay Mathieson <???>
 // Modified by:
 
 #include "wx/dcclient.h"
 #include "wx/math.h"
 
 #include "wx/dcclient.h"
 #include "wx/math.h"
-#include "wx/msw/ole/activex.h"
-
 
 
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-//
-// wxActiveXContainer
-//
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// I don't know why members of tagVARIANT aren't found when compiling
+// with Wine
+#ifndef __WINE__
 
 
+#include "wx/msw/ole/activex.h"
+// autointerfaces that we only use here
+WX_DECLARE_AUTOOLE(wxAutoIOleInPlaceSite, IOleInPlaceSite)
+WX_DECLARE_AUTOOLE(wxAutoIOleDocument, IOleDocument)
+WX_DECLARE_AUTOOLE(wxAutoIPersistStreamInit, IPersistStreamInit)
+WX_DECLARE_AUTOOLE(wxAutoIAdviseSink, IAdviseSink)
+WX_DECLARE_AUTOOLE(wxAutoIProvideClassInfo, IProvideClassInfo)
+WX_DECLARE_AUTOOLE(wxAutoITypeInfo, ITypeInfo)
+WX_DECLARE_AUTOOLE(wxAutoIConnectionPoint, IConnectionPoint)
+WX_DECLARE_AUTOOLE(wxAutoIConnectionPointContainer, IConnectionPointContainer)
+
+DEFINE_EVENT_TYPE(wxEVT_ACTIVEX);
+
+// Ole class helpers (sort of MFC-like) from wxActiveX
 #define DECLARE_OLE_UNKNOWN(cls)\
     private:\
     class TAutoInitInt\
 #define DECLARE_OLE_UNKNOWN(cls)\
     private:\
     class TAutoInitInt\
         if (! ppvObject)\
         {\
             return E_FAIL;\
         if (! ppvObject)\
         {\
             return E_FAIL;\
-        }\
+        };\
         const char *desc = NULL;\
         cls::_GetInterface(this, iid, ppvObject, desc);\
         if (! *ppvObject)\
         {\
             return E_NOINTERFACE;\
         const char *desc = NULL;\
         cls::_GetInterface(this, iid, ppvObject, desc);\
         if (! *ppvObject)\
         {\
             return E_NOINTERFACE;\
-        }\
+        };\
         ((IUnknown * )(*ppvObject))->AddRef();\
         return S_OK;\
         ((IUnknown * )(*ppvObject))->AddRef();\
         return S_OK;\
-    }\
+    };\
     ULONG STDMETHODCALLTYPE cls::AddRef()\
     {\
         InterlockedIncrement(&refCount.l);\
         return refCount.l;\
     ULONG STDMETHODCALLTYPE cls::AddRef()\
     {\
         InterlockedIncrement(&refCount.l);\
         return refCount.l;\
-    }\
+    };\
     ULONG STDMETHODCALLTYPE cls::Release()\
     {\
         if (refCount.l > 0)\
     ULONG STDMETHODCALLTYPE cls::Release()\
     {\
         if (refCount.l > 0)\
@@ -83,7 +93,7 @@
             {\
                 delete this;\
                 return 0;\
             {\
                 delete this;\
                 return 0;\
-            }\
+            };\
             return refCount.l;\
         }\
         else\
             return refCount.l;\
         }\
         else\
     {\
         InterlockedIncrement(&lockCount.l);\
         return lockCount.l;\
     {\
         InterlockedIncrement(&lockCount.l);\
         return lockCount.l;\
-    }\
+    };\
     ULONG STDMETHODCALLTYPE cls::ReleaseLock()\
     {\
         if (lockCount.l > 0)\
     ULONG STDMETHODCALLTYPE cls::ReleaseLock()\
     {\
         if (lockCount.l > 0)\
 #define END_OLE_TABLE\
     }
 
 #define END_OLE_TABLE\
     }
 
+// ============================================================================
+// implementation
+// ============================================================================
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// PixelsToHimetric
+//
+// Utility to convert from pixels to the himetric values in some COM methods
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+
+#define HIMETRIC_PER_INCH   2540
+#define MAP_PIX_TO_LOGHIM(x,ppli)   MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
+
+static void PixelsToHimetric(SIZEL &sz)
+{
+    static int logX = 0;
+    static int logY = 0;
+
+    if (logY == 0)
+    {
+        // initaliase
+        HDC dc = GetDC(NULL);
+        logX = GetDeviceCaps(dc, LOGPIXELSX);
+        logY = GetDeviceCaps(dc, LOGPIXELSY);
+        ReleaseDC(NULL, dc);
+    };
+
+#define HIMETRIC_INCH   2540
+#define CONVERT(x, logpixels)   wxMulDivInt32(HIMETRIC_INCH, (x), (logpixels))
+
+    sz.cx = CONVERT(sz.cx, logX);
+    sz.cy = CONVERT(sz.cy, logY);
+
+#undef CONVERT
+#undef HIMETRIC_INCH
+}
+
 
 
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// FrameSite
+//
+// Handles the actual wxActiveX container implementation
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 class FrameSite :
     public IOleClientSite,
     public IOleInPlaceSiteEx,
 class FrameSite :
     public IOleClientSite,
     public IOleInPlaceSiteEx,
@@ -207,7 +262,7 @@ public:
             case DISPID_AMBIENT_SILENT:
                 V_BOOL(pVarResult)= TRUE;
                 return S_OK;
             case DISPID_AMBIENT_SILENT:
                 V_BOOL(pVarResult)= TRUE;
                 return S_OK;
-#ifndef __WINE__
+
             case DISPID_AMBIENT_APPEARANCE:
                 pVarResult->vt = VT_BOOL;
                 pVarResult->boolVal = m_bAmbientAppearance;
             case DISPID_AMBIENT_APPEARANCE:
                 pVarResult->vt = VT_BOOL;
                 pVarResult->boolVal = m_bAmbientAppearance;
@@ -242,7 +297,7 @@ public:
                 pVarResult->vt = VT_BOOL;
                 pVarResult->boolVal = m_bAmbientShowHatching;
                 break;
                 pVarResult->vt = VT_BOOL;
                 pVarResult->boolVal = m_bAmbientShowHatching;
                 break;
-#endif
+
             default:
                 return DISP_E_MEMBERNOTFOUND;
         }
             default:
                 return DISP_E_MEMBERNOTFOUND;
         }
@@ -326,7 +381,7 @@ public:
         if (! SUCCEEDED(hr))
         {
             return E_UNEXPECTED;
         if (! SUCCEEDED(hr))
         {
             return E_UNEXPECTED;
-        }
+        };
 
         hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc);
         if (! SUCCEEDED(hr))
 
         hr = QueryInterface(IID_IOleInPlaceUIWindow, (void **) ppDoc);
         if (! SUCCEEDED(hr))
@@ -334,7 +389,7 @@ public:
             (*ppFrame)->Release();
             *ppFrame = NULL;
             return E_UNEXPECTED;
             (*ppFrame)->Release();
             *ppFrame = NULL;
             return E_UNEXPECTED;
-        }
+        };
 
         RECT rect;
         ::GetClientRect(m_hWndParent, &rect);
 
         RECT rect;
         ::GetClientRect(m_hWndParent, &rect);
@@ -343,13 +398,13 @@ public:
             lprcPosRect->left = lprcPosRect->top = 0;
             lprcPosRect->right = rect.right;
             lprcPosRect->bottom = rect.bottom;
             lprcPosRect->left = lprcPosRect->top = 0;
             lprcPosRect->right = rect.right;
             lprcPosRect->bottom = rect.bottom;
-        }
+        };
         if (lprcClipRect)
         {
             lprcClipRect->left = lprcClipRect->top = 0;
             lprcClipRect->right = rect.right;
             lprcClipRect->bottom = rect.bottom;
         if (lprcClipRect)
         {
             lprcClipRect->left = lprcClipRect->top = 0;
             lprcClipRect->right = rect.right;
             lprcClipRect->bottom = rect.bottom;
-        }
+        };
 
         memset(lpFrameInfo, 0, sizeof(OLEINPLACEFRAMEINFO));
         lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
 
         memset(lpFrameInfo, 0, sizeof(OLEINPLACEFRAMEINFO));
         lpFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
@@ -368,8 +423,18 @@ public:
     {
         if (m_window->m_oleInPlaceObject.Ok() && lprcPosRect)
         {
     {
         if (m_window->m_oleInPlaceObject.Ok() && lprcPosRect)
         {
+           //
+           // Result of several hours and days of bug hunting -
+           // this is called by an object when it wants to resize
+           // itself to something different then our parent window -
+           // don't let it :)
+           //
+//            m_window->m_oleInPlaceObject->SetObjectRects(
+//                lprcPosRect, lprcPosRect);
+           RECT rcClient;
+           ::GetClientRect(m_hWndParent, &rcClient);
             m_window->m_oleInPlaceObject->SetObjectRects(
             m_window->m_oleInPlaceObject->SetObjectRects(
-                lprcPosRect, lprcPosRect);
+                &rcClient, &rcClient);
         }
         return S_OK;
     }
         }
         return S_OK;
     }
@@ -419,8 +484,8 @@ public:
         case OLEGETMONIKER_UNASSIGN     : return "OLEGETMONIKER_UNASSIGN";
         case OLEGETMONIKER_TEMPFORUSER  : return "OLEGETMONIKER_TEMPFORUSER";
         default                         : return "Bad Enum";
         case OLEGETMONIKER_UNASSIGN     : return "OLEGETMONIKER_UNASSIGN";
         case OLEGETMONIKER_TEMPFORUSER  : return "OLEGETMONIKER_TEMPFORUSER";
         default                         : return "Bad Enum";
-        }
-    }
+        };
+    };
 
     const char *OleGetWhicMonikerStr(DWORD dwWhichMoniker)
     {
 
     const char *OleGetWhicMonikerStr(DWORD dwWhichMoniker)
     {
@@ -430,8 +495,8 @@ public:
         case OLEWHICHMK_OBJREL      : return "OLEWHICHMK_OBJREL";
         case OLEWHICHMK_OBJFULL     : return "OLEWHICHMK_OBJFULL";
         default                     : return "Bad Enum";
         case OLEWHICHMK_OBJREL      : return "OLEWHICHMK_OBJREL";
         case OLEWHICHMK_OBJFULL     : return "OLEWHICHMK_OBJFULL";
         default                     : return "Bad Enum";
-        }
-    }
+        };
+    };
     STDMETHOD(GetMoniker)(DWORD, DWORD, IMoniker **){return E_FAIL;}
     HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER * ppContainer)
     {
     STDMETHOD(GetMoniker)(DWORD, DWORD, IMoniker **){return E_FAIL;}
     HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER * ppContainer)
     {
@@ -458,7 +523,7 @@ public:
     HRESULT STDMETHODCALLTYPE LockContainer(BOOL){return S_OK;}
     //********************IOleItemContainer***************************
     HRESULT STDMETHODCALLTYPE
     HRESULT STDMETHODCALLTYPE LockContainer(BOOL){return S_OK;}
     //********************IOleItemContainer***************************
     HRESULT STDMETHODCALLTYPE
-    #if defined(__WXWINCE__)
+    #ifdef __WXWINCE__
     GetObject
     #elif defined(_UNICODE)
     GetObjectW
     GetObject
     #elif defined(_UNICODE)
     GetObjectW
@@ -558,11 +623,11 @@ public:
                 return E_FAIL;
 
             m_window->m_docView->SetInPlaceSite(inPlaceSite);
                 return E_FAIL;
 
             m_window->m_docView->SetInPlaceSite(inPlaceSite);
-        }
+        };
 
         m_window->m_docView->UIActivate(TRUE);
         return S_OK;
 
         m_window->m_docView->UIActivate(TRUE);
         return S_OK;
-    }
+    };
 
 
 protected:
 
 
 protected:
@@ -601,10 +666,135 @@ DEFINE_OLE_TABLE(FrameSite)
     OLE_IINTERFACE(IOleDocumentSite)
     OLE_IINTERFACE(IAdviseSink)
     OLE_IINTERFACE(IOleControlSite)
     OLE_IINTERFACE(IOleDocumentSite)
     OLE_IINTERFACE(IAdviseSink)
     OLE_IINTERFACE(IOleControlSite)
-END_OLE_TABLE
+END_OLE_TABLE;
+
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// wxActiveXEvents
+//
+// Handles and sends activex events received from the ActiveX control
+// to the appropriate wxEvtHandler
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+class wxActiveXEvents : public IDispatch
+{
+private:
+    DECLARE_OLE_UNKNOWN(wxActiveXEvents);
+
+
+    wxActiveXContainer *m_activeX;
+    IID m_customId;
+    bool m_haveCustomId;
+
+    friend bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc);
+
+public:
+    wxActiveXEvents(wxActiveXContainer *ax) : m_activeX(ax), m_haveCustomId(false) {}
+    wxActiveXEvents(wxActiveXContainer *ax, REFIID iid) : m_activeX(ax), m_haveCustomId(true), m_customId(iid) {}
+    virtual ~wxActiveXEvents()
+    {
+    }
+
+    // IDispatch
+    STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR**, unsigned int, LCID, DISPID*)
+    {
+        return E_NOTIMPL;
+    }
+
+    STDMETHODIMP GetTypeInfo(unsigned int, LCID, ITypeInfo**)
+    {
+        return E_NOTIMPL;
+    }
+
+    STDMETHODIMP GetTypeInfoCount(unsigned int*)
+    {
+        return E_NOTIMPL;
+    }
 
 
 
 
-wxActiveXContainer::wxActiveXContainer(wxWindow * parent, REFIID iid, IUnknown* pUnk)
+    STDMETHODIMP Invoke(DISPID dispIdMember, REFIID WXUNUSED(riid),
+                        LCID WXUNUSED(lcid),
+                          WORD wFlags, DISPPARAMS * pDispParams,
+                          VARIANT * WXUNUSED(pVarResult), EXCEPINFO * WXUNUSED(pExcepInfo),
+                          unsigned int * WXUNUSED(puArgErr))
+    {
+        if (wFlags & (DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
+            return E_NOTIMPL;
+
+        wxASSERT(m_activeX);
+
+        // ActiveX Event
+
+        // Dispatch Event
+        wxActiveXEvent  event;
+        event.SetEventType(wxEVT_ACTIVEX);
+        event.m_params.NullList();
+        event.m_dispid = dispIdMember;
+
+        // arguments
+        if (pDispParams)
+        {
+            for (DWORD i = pDispParams->cArgs; i > 0; i--)
+            {
+                VARIANTARG& va = pDispParams->rgvarg[i-1];
+                wxVariant vx;
+
+//                        vx.SetName(px.name);
+                wxConvertOleToVariant(va, vx);
+                event.m_params.Append(vx);
+            }
+        }
+
+        // process the events from the activex method
+           m_activeX->ProcessEvent(event);
+        for (DWORD i = 0; i < pDispParams->cArgs; i++)
+        {
+            VARIANTARG& va = pDispParams->rgvarg[i];
+            wxVariant& vx =
+                event.m_params[pDispParams->cArgs - i - 1];
+            wxConvertVariantToOle(vx, va);
+        }
+
+        if(event.GetSkipped())
+            return DISP_E_MEMBERNOTFOUND;
+
+        return S_OK;
+    }
+};
+
+bool wxActiveXEventsInterface(wxActiveXEvents *self, REFIID iid, void **_interface, const char *&desc)
+{
+    if (self->m_haveCustomId && IsEqualIID(iid, self->m_customId))
+    {
+//        WXOLE_TRACE("Found Custom Dispatch Interface");
+        *_interface = (IUnknown *) (IDispatch *) self;
+        desc = "Custom Dispatch Interface";
+        return true;
+    };
+
+    return false;
+}
+
+DEFINE_OLE_TABLE(wxActiveXEvents)
+    OLE_IINTERFACE(IUnknown)
+    OLE_INTERFACE(IID_IDispatch, IDispatch)
+    OLE_INTERFACE_CUSTOM(wxActiveXEventsInterface)
+END_OLE_TABLE;
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//
+// wxActiveXContainer
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+//---------------------------------------------------------------------------
+// wxActiveXContainer Constructor
+//
+// Initializes members and creates the native ActiveX container
+//---------------------------------------------------------------------------
+wxActiveXContainer::wxActiveXContainer(wxWindow * parent,
+                                       REFIID iid, IUnknown* pUnk)
     : m_realparent(parent)
 {
     m_bAmbientUserMode = true;
     : m_realparent(parent)
 {
     m_bAmbientUserMode = true;
@@ -612,6 +802,12 @@ wxActiveXContainer::wxActiveXContainer(wxWindow * parent, REFIID iid, IUnknown*
     CreateActiveX(iid, pUnk);
 }
 
     CreateActiveX(iid, pUnk);
 }
 
+//---------------------------------------------------------------------------
+// wxActiveXContainer Destructor
+//
+// Destroys members (the FrameSite et al. are destroyed implicitly
+// through COM ref counting)
+//---------------------------------------------------------------------------
 wxActiveXContainer::~wxActiveXContainer()
 {
     // disconnect connection points
 wxActiveXContainer::~wxActiveXContainer()
 {
     // disconnect connection points
@@ -633,6 +829,14 @@ wxActiveXContainer::~wxActiveXContainer()
     }
 }
 
     }
 }
 
+//---------------------------------------------------------------------------
+// wxActiveXContainer::CreateActiveX
+//
+// Actually creates the ActiveX container through the FrameSite
+// and sets up ActiveX events
+//
+// TODO: Document this more
+//---------------------------------------------------------------------------
 void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
 {
     HRESULT hret;
 void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
 {
     HRESULT hret;
@@ -652,6 +856,111 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
     // Get Dispatch interface
     hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX);
 
     // Get Dispatch interface
     hret = m_Dispatch.QueryInterface(IID_IDispatch, m_ActiveX);
 
+    //
+    // SETUP TYPEINFO AND ACTIVEX EVENTS
+    //
+
+    // get type info via class info
+    wxAutoIProvideClassInfo classInfo(IID_IProvideClassInfo, m_ActiveX);
+    wxASSERT(classInfo.Ok());
+
+    // type info
+    wxAutoITypeInfo typeInfo;
+    hret = classInfo->GetClassInfo(typeInfo.GetRef());
+    wxASSERT(typeInfo.Ok());
+
+    // TYPEATTR
+    TYPEATTR *ta = NULL;
+    hret = typeInfo->GetTypeAttr(&ta);
+    wxASSERT(ta);
+
+    // this should be a TKIND_COCLASS
+    wxASSERT(ta->typekind == TKIND_COCLASS);
+
+    // iterate contained interfaces
+    for (int i = 0; i < ta->cImplTypes; i++)
+    {
+        HREFTYPE rt = 0;
+
+        // get dispatch type info handle
+        hret = typeInfo->GetRefTypeOfImplType(i, &rt);
+        if (! SUCCEEDED(hret))
+            continue;
+
+        // get dispatch type info interface
+        wxAutoITypeInfo  ti;
+        hret = typeInfo->GetRefTypeInfo(rt, ti.GetRef());
+        if (! ti.Ok())
+            continue;
+
+        // check if default event sink
+        bool defInterface = false;
+        bool defEventSink = false;
+        int impTypeFlags = 0;
+        typeInfo->GetImplTypeFlags(i, &impTypeFlags);
+
+        if (impTypeFlags & IMPLTYPEFLAG_FDEFAULT)
+        {
+            if (impTypeFlags & IMPLTYPEFLAG_FSOURCE)
+            {
+                // WXOLE_TRACEOUT("Default Event Sink");
+                defEventSink = true;
+                if (impTypeFlags & IMPLTYPEFLAG_FDEFAULTVTABLE)
+                {
+                    // WXOLE_TRACEOUT("*ERROR* - Default Event Sink is via vTable");
+                    defEventSink = false;
+                    wxFAIL_MSG(wxT("Default event sink is in vtable!"));
+                }
+            }
+            else
+            {
+                // WXOLE_TRACEOUT("Default Interface");
+                defInterface = true;
+            }
+        }
+
+
+        // wxAutoOleInterface<> assumes a ref has already been added
+        // TYPEATTR
+        TYPEATTR *ta = NULL;
+        hret = ti->GetTypeAttr(&ta);
+        wxASSERT(ta);
+
+        if (ta->typekind == TKIND_DISPATCH)
+        {
+            // WXOLE_TRACEOUT("GUID = " << GetIIDName(ta->guid).c_str());
+            if (defEventSink)
+            {
+                wxAutoIConnectionPoint    cp;
+                DWORD                    adviseCookie = 0;
+
+                wxAutoIConnectionPointContainer cpContainer(IID_IConnectionPointContainer, m_ActiveX);
+                wxASSERT( cpContainer.Ok());
+
+                HRESULT hret =
+                    cpContainer->FindConnectionPoint(ta->guid, cp.GetRef());
+                wxASSERT ( SUCCEEDED(hret));
+
+                IDispatch* disp;
+                frame->QueryInterface(IID_IDispatch, (void**)&disp);
+                hret = cp->Advise(new wxActiveXEvents(this, ta->guid),
+                                  &adviseCookie);
+                wxASSERT_MSG( SUCCEEDED(hret),
+                    wxString::Format(wxT("Cannot connect!\nHRESULT:%X"), hret)
+                            );
+            }
+        }
+
+        ti->ReleaseTypeAttr(ta);
+    }
+
+    // free
+    typeInfo->ReleaseTypeAttr(ta);
+
+    //
+    // END
+    //
+
     // Get IOleObject interface
     hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
     wxASSERT(SUCCEEDED(hret));
     // Get IOleObject interface
     hret = m_oleObject.QueryInterface(IID_IOleObject, m_ActiveX);
     wxASSERT(SUCCEEDED(hret));
@@ -663,6 +972,8 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
     // document advise
     m_docAdviseCookie = 0;
     hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
     // document advise
     m_docAdviseCookie = 0;
     hret = m_oleObject->Advise(adviseSink, &m_docAdviseCookie);
+    // TODO:Needed?
+//    hret = m_viewObject->SetAdvise(DVASPECT_CONTENT, 0, adviseSink);
     m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
     OleSetContainedObject(m_oleObject, TRUE);
     OleRun(m_oleObject);
     m_oleObject->SetHostNames(L"wxActiveXContainer", NULL);
     OleSetContainedObject(m_oleObject, TRUE);
     OleRun(m_oleObject);
@@ -739,6 +1050,8 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
 
         pWnd->Connect(id, wxEVT_SIZE,
             wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this);
 
         pWnd->Connect(id, wxEVT_SIZE,
             wxSizeEventHandler(wxActiveXContainer::OnSize), 0, this);
+//        this->Connect(GetId(), wxEVT_PAINT,
+//            wxPaintEventHandler(wxActiveXContainer::OnPaint), 0, this);
         pWnd->Connect(id, wxEVT_SET_FOCUS,
             wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this);
         pWnd->Connect(id, wxEVT_KILL_FOCUS,
         pWnd->Connect(id, wxEVT_SET_FOCUS,
             wxFocusEventHandler(wxActiveXContainer::OnSetFocus), 0, this);
         pWnd->Connect(id, wxEVT_KILL_FOCUS,
@@ -746,34 +1059,12 @@ void wxActiveXContainer::CreateActiveX(REFIID iid, IUnknown* pUnk)
     }
 }
 
     }
 }
 
-#define HIMETRIC_PER_INCH   2540
-#define MAP_PIX_TO_LOGHIM(x,ppli)   MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
-
-static void PixelsToHimetric(SIZEL &sz)
-{
-    static int logX = 0;
-    static int logY = 0;
-
-    if (logY == 0)
-    {
-        // initaliase
-        HDC dc = GetDC(NULL);
-        logX = GetDeviceCaps(dc, LOGPIXELSX);
-        logY = GetDeviceCaps(dc, LOGPIXELSY);
-        ReleaseDC(NULL, dc);
-    };
-
-#define HIMETRIC_INCH   2540
-#define CONVERT(x, logpixels)   wxMulDivInt32(HIMETRIC_INCH, (x), (logpixels))
-
-    sz.cx = CONVERT(sz.cx, logX);
-    sz.cy = CONVERT(sz.cy, logY);
-
-#undef CONVERT
-#undef HIMETRIC_INCH
-}
-
-
+//---------------------------------------------------------------------------
+// wxActiveXContainer::OnSize
+//
+// Called when the parent is resized - we need to do this to actually
+// move the ActiveX control to where the parent is
+//---------------------------------------------------------------------------
 void wxActiveXContainer::OnSize(wxSizeEvent& event)
 {
     int w, h;
 void wxActiveXContainer::OnSize(wxSizeEvent& event)
 {
     int w, h;
@@ -791,6 +1082,9 @@ void wxActiveXContainer::OnSize(wxSizeEvent& event)
     // extents are in HIMETRIC units
     if (m_oleObject.Ok())
     {
     // extents are in HIMETRIC units
     if (m_oleObject.Ok())
     {
+        m_oleObject->DoVerb(OLEIVERB_HIDE, 0, m_clientSite, 0,
+            (HWND)m_realparent->GetHWND(), &posRect);
+
         SIZEL sz = {w, h};
         PixelsToHimetric(sz);
 
         SIZEL sz = {w, h};
         PixelsToHimetric(sz);
 
@@ -799,7 +1093,10 @@ void wxActiveXContainer::OnSize(wxSizeEvent& event)
         m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2);
         if (sz2.cx !=  sz.cx || sz.cy != sz2.cy)
             m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
         m_oleObject->GetExtent(DVASPECT_CONTENT, &sz2);
         if (sz2.cx !=  sz.cx || sz.cy != sz2.cy)
             m_oleObject->SetExtent(DVASPECT_CONTENT, &sz);
-    };
+
+        m_oleObject->DoVerb(OLEIVERB_SHOW, 0, m_clientSite, 0,
+            (HWND)m_realparent->GetHWND(), &posRect);
+    }
 
     if (m_oleInPlaceObject.Ok())
         m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
 
     if (m_oleInPlaceObject.Ok())
         m_oleInPlaceObject->SetObjectRects(&posRect, &posRect);
@@ -807,12 +1104,39 @@ void wxActiveXContainer::OnSize(wxSizeEvent& event)
     event.Skip();
 }
 
     event.Skip();
 }
 
+//---------------------------------------------------------------------------
+// wxActiveXContainer::OnPaint
+//
+// Called when the parent is resized - repaints the ActiveX control
+//---------------------------------------------------------------------------
 void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
 {
     wxPaintDC dc(this);
     // Draw only when control is windowless or deactivated
     if (m_viewObject)
     {
 void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
 {
     wxPaintDC dc(this);
     // Draw only when control is windowless or deactivated
     if (m_viewObject)
     {
+#if 0
+        dc.BeginDrawing();
+        RECT rcClient;
+        ::GetClientRect((HWND)GetHandle(), &rcClient);
+
+        HBITMAP hBitmap = CreateCompatibleBitmap((HDC)dc.GetHDC(),
+                                rcClient.right - rcClient.left,
+                                rcClient.bottom - rcClient.top);
+        HDC hdcCompatible = ::CreateCompatibleDC((HDC)dc.GetHDC());
+        HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcCompatible, hBitmap);
+
+        m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
+            hdcCompatible, (RECTL *) &rcClient, (RECTL *) &rcClient, NULL, 0);
+
+        ::BitBlt((HDC)dc.GetHDC(), 0, 0, rcClient.right, rcClient.bottom,  hdcCompatible, 0, 0, SRCCOPY);
+
+        ::SelectObject(hdcCompatible, hBitmapOld);
+        ::DeleteObject(hBitmap);
+        ::DeleteDC(hdcCompatible);
+        dc.EndDrawing();
+#else
+        dc.BeginDrawing();
         int w, h;
         GetParent()->GetSize(&w, &h);
         RECT posRect;
         int w, h;
         GetParent()->GetSize(&w, &h);
         RECT posRect;
@@ -821,20 +1145,21 @@ void wxActiveXContainer::OnPaint(wxPaintEvent& WXUNUSED(event))
         posRect.right = w;
         posRect.bottom = h;
 
         posRect.right = w;
         posRect.bottom = h;
 
-#if defined(_WIN32_WCE) && _WIN32_WCE < 400
-        ::InvalidateRect(m_oleObjectHWND, NULL, false);
-#else
         ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
         ::RedrawWindow(m_oleObjectHWND, NULL, NULL, RDW_INTERNALPAINT);
-#endif
         RECTL *prcBounds = (RECTL *) &posRect;
         m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
             (HDC)dc.GetHDC(), prcBounds, NULL, NULL, 0);
         RECTL *prcBounds = (RECTL *) &posRect;
         m_viewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL,
             (HDC)dc.GetHDC(), prcBounds, NULL, NULL, 0);
-    }
 
 
-//  We've got this one I think
-//    event.Skip();
+        dc.EndDrawing();
+#endif
+    }
 }
 
 }
 
+//---------------------------------------------------------------------------
+// wxActiveXContainer::OnSetFocus
+//
+// Called when the focus is set on the parent - activates the activex control
+//---------------------------------------------------------------------------
 void wxActiveXContainer::OnSetFocus(wxFocusEvent& event)
 {
     if (m_oleInPlaceActiveObject.Ok())
 void wxActiveXContainer::OnSetFocus(wxFocusEvent& event)
 {
     if (m_oleInPlaceActiveObject.Ok())
@@ -843,6 +1168,12 @@ void wxActiveXContainer::OnSetFocus(wxFocusEvent& event)
     event.Skip();
 }
 
     event.Skip();
 }
 
+//---------------------------------------------------------------------------
+// wxActiveXContainer::OnKillFocus
+//
+// Called when the focus is killed on the parent -
+// deactivates the activex control
+//---------------------------------------------------------------------------
 void wxActiveXContainer::OnKillFocus(wxFocusEvent& event)
 {
     if (m_oleInPlaceActiveObject.Ok())
 void wxActiveXContainer::OnKillFocus(wxFocusEvent& event)
 {
     if (m_oleInPlaceActiveObject.Ok())
@@ -850,3 +1181,6 @@ void wxActiveXContainer::OnKillFocus(wxFocusEvent& event)
 
     event.Skip();
 }
 
     event.Skip();
 }
+
+#endif
+// __WINE__
index 1951484bbddd7bc29c18bfffbd62bd775df06f14..b461f9d96571f3d60c154370de0e036ca644a2b5 100644 (file)
@@ -1,6 +1,6 @@
 /////////////////////////////////////////////////////////////////////////////
 // Name:        src/unix/mediactrl.cpp
 /////////////////////////////////////////////////////////////////////////////
 // Name:        src/unix/mediactrl.cpp
-// Purpose:     Built-in Media Backends for Unix
+// Purpose:     GStreamer backend for Unix
 // Author:      Ryan Norton <wxprojects@comcast.net>
 // Modified by:
 // Created:     02/04/05
 // Author:      Ryan Norton <wxprojects@comcast.net>
 // Modified by:
 // Created:     02/04/05
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-//===========================================================================
-//  DECLARATIONS
-//===========================================================================
-
-//---------------------------------------------------------------------------
-// Pre-compiled header stuff
-//---------------------------------------------------------------------------
-
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
-#ifdef __BORLANDC__
-#pragma hdrstop
-#endif
-
-//---------------------------------------------------------------------------
-// Includes
-//---------------------------------------------------------------------------
 #include "wx/mediactrl.h"
 
 #include "wx/mediactrl.h"
 
-//---------------------------------------------------------------------------
-// Compilation guard
-//---------------------------------------------------------------------------
 #if wxUSE_MEDIACTRL
 
 #if wxUSE_MEDIACTRL
 
-//===========================================================================
-//  BACKEND DECLARATIONS
-//===========================================================================
-
-//---------------------------------------------------------------------------
-//
-//  wxGStreamerMediaBackend
-//
-//TODO:
-//TODO:  This is really not the best way to play-stop -
-//TODO:  it should just have one playbin and stick with it the whole
-//TODO:  instance of wxGStreamerMediaBackend - but stopping appears
-//TODO:  to invalidate the playbin object...
-//TODO:
-//
-//---------------------------------------------------------------------------
 #if wxUSE_GSTREAMER
 
 #if wxUSE_GSTREAMER
 
-//---------------------------------------------------------------------------
-//  GStreamer Includes
-//---------------------------------------------------------------------------
-#include <gst/gst.h>
-#include <gst/xoverlay/xoverlay.h>
+#include <gst/gst.h>                // main gstreamer header
 
 
-#include <string.h> //strstr
+// xoverlay/video stuff, gst-gconf for 0.8
+#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10
+#   include <gst/interfaces/xoverlay.h>
+#else
+#   include <gst/xoverlay/xoverlay.h>
+#   include <gst/gconf/gconf.h>        // gstreamer glib configuration
+#endif
 
 
-#include "wx/log.h"
+#include "wx/log.h"                 // wxLogDebug/wxLogSysError/wxLogTrace
+#include "wx/app.h"                 // wxTheApp->argc, wxTheApp->argv
+#include "wx/thread.h"              // wxMutex/wxMutexLocker
+#include "wx/timer.h"               // wxTimer
 
 #ifdef __WXGTK__
 
 #ifdef __WXGTK__
-    //for <gdk/gdkx.h>/related for GDK_WINDOW_XWINDOW
-#    include "wx/gtk/win_gtk.h"
-#    include <gtk/gtksignal.h>
-#    if wxUSE_DYNLIB_CLASS
-#        include "wx/dynlib.h"
-#    endif
-//#    include <gst/gconf/gconf.h> //gstreamer gnome interface - needs deps
+#    include "wx/gtk/win_gtk.h"     // for <gdk/gdkx.h>/GDK_WINDOW_XWINDOW
+#endif
+
+//-----------------------------------------------------------------------------
+// Discussion of internals
+//-----------------------------------------------------------------------------
+
+/*
+   This is the GStreamer backend for unix. Currently we require 0.8 or
+   0.10. Here we use the "playbin" GstElement for ease of use.
+
+   Note that now we compare state change functions to GST_STATE_FAILURE
+   now rather than GST_STATE_SUCCESS as newer gstreamer versions return
+   non-success values for returns that are otherwise successful but not
+   immediate.
+
+   Also this probably doesn't work with anything other than wxGTK at the
+   moment but with a tad bit of work it could theorectically work in
+   straight wxX11 et al.
+
+   One last note is that resuming from pausing/seeking can result
+   in erratic video playback (GStreamer-based bug, happens in totem as well)
+   - this is better in 0.10, however. One thing that might make it worse
+   here is that we don't preserve the aspect ratio of the video and stretch
+   it to the whole window.
+
+   Note that there are some things used here that could be undocumented -
+   for reference see the media player Kiss and Totem as well as some
+   other sources. There was a backend for a kde media player as well
+   that attempted thread-safety...
+
+   Then there is the issue of m_asynclock. This serves several purposes:
+   1) It prevents the C callbacks from sending wx state change events
+      so that we don't get duplicate ones in 0.8
+   2) It makes the sync and async handlers in 0.10 not drop any
+      messages so that while we are polling it we get the messages in
+      SyncStateChange instead of the queue.
+   3) Keeps the pausing in Stop() synchronous
+
+   RN: Note that I've tried to follow the wxGTK conventions here as close
+   as possible. In the implementation the C Callbacks come first, then
+   the internal functions, then the public ones. Set your vi to 80
+   characters people :).
+*/
+
+//=============================================================================
+//  Declarations
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+//  GStreamer (most version compatability) macros
+//-----------------------------------------------------------------------------
+
+// In 0.9 there was a HUGE change to GstQuery and the
+// gst_element_query function changed dramatically and split off
+// into two seperate ones
+#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR <= 8
+#    define wxGst_element_query_duration(e, f, p) \
+                gst_element_query(e, GST_QUERY_TOTAL, f, p)
+#    define wxGst_element_query_position(e, f, p) \
+                gst_element_query(e, GST_QUERY_POSITION, f, p)
+#elif GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR == 9
+// However, the actual 0.9 version has a slightly different definition
+// and instead of gst_element_query_duration it has two parameters to
+// gst_element_query_position instead
+#    define wxGst_element_query_duration(e, f, p) \
+                gst_element_query_position(e, f, 0, p)
+#    define wxGst_element_query_position(e, f, p) \
+                gst_element_query_position(e, f, p, 0)
+#else
+#    define wxGst_element_query_duration \
+                gst_element_query_duration
+#    define wxGst_element_query_position \
+                gst_element_query_position
+#endif
+
+// Other 0.10 macros
+#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10
+#   define GST_STATE_FAILURE GST_STATE_CHANGE_FAILURE
+#   define GST_STATE_SUCCESS GST_STATE_CHANGE_SUCCESS
+#   define GstElementState GstState
+#   define gst_gconf_get_default_video_sink() \
+        gst_element_factory_make ("gconfvideosink", "video-sink");
+#   define gst_gconf_get_default_audio_sink() \
+        gst_element_factory_make ("gconfaudiosink", "audio-sink");
 #endif
 
 #endif
 
+// Max wait time for element state waiting - GST_CLOCK_TIME_NONE for inf
+#define wxGSTREAMER_TIMEOUT (100 * GST_MSECOND) // Max 100 milliseconds
+
+//-----------------------------------------------------------------------------
+// wxGTK Debugging and idle stuff
+//-----------------------------------------------------------------------------
+#ifdef __WXGTK__
+
+#   ifdef __WXDEBUG__
+#       if wxUSE_THREADS
+#           define DEBUG_MAIN_THREAD \
+                if (wxThread::IsMain() && g_mainThreadLocked) \
+                    wxPrintf(wxT("gui reentrance"));
+#       else
+#           define DEBUG_MAIN_THREAD
+#       endif
+#   else
+#      define DEBUG_MAIN_THREAD
+#   endif // Debug
 
 
-class WXDLLIMPEXP_MEDIA wxGStreamerMediaBackend : public wxMediaBackend
+extern void wxapp_install_idle_handler();
+extern bool g_isIdle;
+extern bool g_mainThreadLocked;
+#endif // wxGTK
+
+//-----------------------------------------------------------------------------
+//  wxLogTrace mask string
+//-----------------------------------------------------------------------------
+#define wxTRACE_GStreamer wxT("GStreamer")
+
+//-----------------------------------------------------------------------------
+//
+//  wxGStreamerMediaBackend
+//
+//-----------------------------------------------------------------------------
+class WXDLLIMPEXP_MEDIA
+    wxGStreamerMediaBackend : public wxMediaBackendCommonBase
 {
 public:
 
 {
 public:
 
@@ -107,391 +191,548 @@ public:
     virtual double GetPlaybackRate();
     virtual bool SetPlaybackRate(double dRate);
 
     virtual double GetPlaybackRate();
     virtual bool SetPlaybackRate(double dRate);
 
-    void Cleanup();
-
-    static void OnFinish(GstElement *play,  gpointer data);
-    static void OnError (GstElement *play,  GstElement *src,
-                         GError     *err,   gchar      *debug,
-                         gpointer    data);
-    static void OnVideoCapsReady(GstPad* pad,  GParamSpec* pspec, gpointer data);
-
-    static bool TransCapsToVideoSize(wxGStreamerMediaBackend* be, GstPad* caps);
-    void PostRecalcSize();
-
-#ifdef __WXGTK__
-    static gint OnGTKRealize(GtkWidget* theWidget, wxGStreamerMediaBackend* be);
-#endif
-
-    GstElement* m_player;       //GStreamer media element
+    virtual wxLongLong GetDownloadProgress();
+    virtual wxLongLong GetDownloadTotal();
+
+    virtual bool SetVolume(double dVolume);
+    virtual double GetVolume();
+
+    //------------implementation from now on-----------------------------------
+    wxMediaCtrl* GetControl() { return m_ctrl; } // for C Callbacks
+    void HandleStateChange(GstElementState oldstate, GstElementState newstate);
+    bool QueryVideoSizeFromElement(GstElement* element);
+    bool QueryVideoSizeFromPad(GstPad* caps);
+    void SetupXOverlay();
+    bool SyncStateChange(GstElement* element, GstElementState state,
+                         gint64 llTimeout = wxGSTREAMER_TIMEOUT);
+    bool TryAudioSink(GstElement* audiosink);
+    bool TryVideoSink(GstElement* videosink);
+
+    GstElement*     m_playbin;      // GStreamer media element
+    wxSize          m_videoSize;    // Cached actual video size
+    double          m_dRate;        // Current playback rate -
+                                    // see GetPlaybackRate for notes
+    wxLongLong      m_llPausedPos;  // Paused position - see Pause()
+    GstXOverlay*    m_xoverlay;     // X Overlay that contains the GST video
+    wxMutex         m_asynclock;    // See "discussion of internals"
+    class wxGStreamerMediaEventHandler* m_eventHandler; // see below
+
+    friend class wxGStreamerMediaEventHandler;
+    friend class wxGStreamerLoadWaitTimer;
+    DECLARE_DYNAMIC_CLASS(wxGStreamerMediaBackend);
+};
 
 
-    wxSize      m_videoSize;
-    wxControl*  m_ctrl;
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaEventHandler
+//
+// OK, this will take an explanation - basically gstreamer callbacks
+// are issued in a seperate thread, and in this thread we may not set
+// the state of the playbin, so we need to send a wx event in that
+// callback so that we set the state of the media and other stuff
+// like GUI calls.
+//-----------------------------------------------------------------------------
+class wxGStreamerMediaEventHandler : public wxEvtHandler
+{
+    public:
+    wxGStreamerMediaEventHandler(wxGStreamerMediaBackend* be) : m_be(be)
+    {
+        this->Connect(wxID_ANY, wxEVT_MEDIA_FINISHED,
+           wxMediaEventHandler(wxGStreamerMediaEventHandler::OnMediaFinish));
+    }
 
 
-    wxLongLong m_nPausedPos;
+    void OnMediaFinish(wxMediaEvent& event);
 
 
-    DECLARE_DYNAMIC_CLASS(wxGStreamerMediaBackend);
+    wxGStreamerMediaBackend* m_be;
 };
 
 };
 
-
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-//
-// wxGStreamerMediaBackend
-//
-//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+//=============================================================================
+// Implementation
+//=============================================================================
 
 IMPLEMENT_DYNAMIC_CLASS(wxGStreamerMediaBackend, wxMediaBackend)
 
 
 IMPLEMENT_DYNAMIC_CLASS(wxGStreamerMediaBackend, wxMediaBackend)
 
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend Constructor
+//-----------------------------------------------------------------------------
 //
 //
-// Sets m_player to NULL signifying we havn't loaded anything yet
-//---------------------------------------------------------------------------
-wxGStreamerMediaBackend::wxGStreamerMediaBackend() : m_player(NULL), m_videoSize(0,0)
-{
-}
-
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend Destructor
+// C Callbacks
 //
 //
-// Stops/cleans up memory
-//---------------------------------------------------------------------------
-wxGStreamerMediaBackend::~wxGStreamerMediaBackend()
-{
-    Cleanup();
-}
+//-----------------------------------------------------------------------------
 
 
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend::OnGTKRealize
+//-----------------------------------------------------------------------------
+// "expose_event" from m_ctrl->m_wxwindow
 //
 //
-// If the window wasn't realized when Load was called, this is the
-// callback for when it is.
+// Handle GTK expose event from our window - here we hopefully
+// redraw the video in the case of pausing and other instances...
+// (Returns TRUE to pass to other handlers, FALSE if not)
 //
 //
-// 1) Installs GTK idle handler if it doesn't exist
-// 2) Yeilds to avoid an X11 bug (?)
-// 3) Tells GStreamer to play the video in our control
-//---------------------------------------------------------------------------
+// TODO: Do a DEBUG_MAIN_THREAD/install_idle_handler here?
+//-----------------------------------------------------------------------------
 #ifdef __WXGTK__
 #ifdef __WXGTK__
+extern "C" {
+static gboolean gtk_window_expose_callback(GtkWidget *widget,
+                                           GdkEventExpose *event,
+                                           wxGStreamerMediaBackend *be)
+{
+    if(event->count > 0)
+        return FALSE;
 
 
-#ifdef __WXDEBUG__
+    GdkWindow *window = GTK_PIZZA(be->GetControl()->m_wxwindow)->bin_window;
 
 
-#if wxUSE_THREADS
-#   define DEBUG_MAIN_THREAD if (wxThread::IsMain() && g_mainThreadLocked) printf("gui reentrance");
-#else
-#   define DEBUG_MAIN_THREAD
-#endif
-#else
-#define DEBUG_MAIN_THREAD
-#endif // Debug
+    // I've seen this reccommended somewhere...
+    // TODO: Is this needed? Maybe it is just cruft...
+    // gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(be->m_xoverlay),
+    //                              GDK_WINDOW_XWINDOW( window ) );
 
 
-extern void wxapp_install_idle_handler();
-extern bool g_isIdle;
-extern bool g_mainThreadLocked;
+    // If we have actual video.....
+    if(!(be->m_videoSize.x==0&&be->m_videoSize.y==0) &&
+       GST_STATE(be->m_playbin) >= GST_STATE_PAUSED)
+    {
+        // GST Doesn't redraw automatically while paused
+        // Plus, the video sometimes doesn't redraw when it looses focus
+        // or is painted over so we just tell it to redraw...
+        gst_x_overlay_expose(be->m_xoverlay);
+    }
+    else
+    {
+        // draw a black background like some other backends do....
+        gdk_draw_rectangle (window, widget->style->black_gc, TRUE, 0, 0,
+                            widget->allocation.width,
+                            widget->allocation.height);
+    }
 
 
-gint wxGStreamerMediaBackend::OnGTKRealize(GtkWidget* theWidget,
-                                           wxGStreamerMediaBackend* be)
+    return FALSE;
+}
+}
+#endif // wxGTK
+
+//-----------------------------------------------------------------------------
+// "realize" from m_ctrl->m_wxwindow
+//
+// If the window wasn't realized when Load was called, this is the
+// callback for when it is - the purpose of which is to tell
+// GStreamer to play the video in our control
+//-----------------------------------------------------------------------------
+#ifdef __WXGTK__
+extern "C" {
+static gint gtk_window_realize_callback(GtkWidget* theWidget,
+                                        wxGStreamerMediaBackend* be)
 {
 {
-    DEBUG_MAIN_THREAD
+    DEBUG_MAIN_THREAD // TODO: Is this neccessary?
 
 
-    if (g_isIdle)
+    if (g_isIdle)   // FIXME: Why is needed? For wxYield? ??
         wxapp_install_idle_handler();
 
         wxapp_install_idle_handler();
 
-    wxYield();    //FIXME: X Server gets an error if I don't do this or a messagebox beforehand?!?!??
+    wxYield();    // FIXME: RN: X Server gets an error/crash if I don't do
+                  //       this or a messagebox beforehand?!?!??
 
     GdkWindow *window = GTK_PIZZA(theWidget)->bin_window;
     wxASSERT(window);
 
 
     GdkWindow *window = GTK_PIZZA(theWidget)->bin_window;
     wxASSERT(window);
 
-    GstElement* videosink;
-    g_object_get (G_OBJECT (be->m_player), "video-sink", &videosink, NULL);
-
-    GstElement* overlay = gst_bin_get_by_interface (GST_BIN (videosink),
-                                    GST_TYPE_X_OVERLAY);
-    gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(overlay),
+    gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(be->m_xoverlay),
                                 GDK_WINDOW_XWINDOW( window )
                                 );
                                 GDK_WINDOW_XWINDOW( window )
                                 );
-
+    g_signal_connect (be->GetControl()->m_wxwindow,
+                      "expose_event",
+                      G_CALLBACK(gtk_window_expose_callback), be);
     return 0;
 }
     return 0;
 }
+}
+#endif // wxGTK
 
 
-
-#endif
-
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend::Cleanup
+//-----------------------------------------------------------------------------
+// "state-change" from m_playbin/GST_MESSAGE_STATE_CHANGE
+//
+// Called by gstreamer when the state changes - here we
+// send the appropriate corresponding wx event.
 //
 //
-// Frees the gstreamer interfaces if there were any created
-//---------------------------------------------------------------------------
-void wxGStreamerMediaBackend::Cleanup()
+// 0.8 only as HandleStateChange does this in both versions
+//-----------------------------------------------------------------------------
+#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR < 10
+extern "C" {
+static void gst_state_change_callback(GstElement *play,
+                                      GstElementState oldstate,
+                                      GstElementState newstate,
+                                      wxGStreamerMediaBackend* be)
 {
 {
-    if(m_player && GST_IS_OBJECT(m_player))
+    if(be->m_asynclock.TryLock() == wxMUTEX_NO_ERROR)
     {
     {
-        gst_element_set_state (m_player, GST_STATE_NULL);
-        gst_object_unref (GST_OBJECT (m_player));
+        be->HandleStateChange(oldstate, newstate);
+        be->m_asynclock.Unlock();
     }
 }
     }
 }
+}
+#endif // <0.10
 
 
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend::CreateControl
+//-----------------------------------------------------------------------------
+// "eos" from m_playbin/GST_MESSAGE_EOS
 //
 //
-// Initializes GStreamer and creates the wx side of our media control
-//---------------------------------------------------------------------------
-bool wxGStreamerMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
-                                wxWindowID id,
-                                const wxPoint& pos,
-                                const wxSize& size,
-                                long style,
-                                const wxValidator& validator,
-                                const wxString& name)
+// Called by gstreamer when the media is done playing ("end of stream")
+//-----------------------------------------------------------------------------
+extern "C" {
+static void gst_finish_callback(GstElement *play,
+                                wxGStreamerMediaBackend* be)
 {
 {
-    //init gstreamer
-    gst_init(NULL, NULL);
-
-    m_ctrl = ctrl;
-
-    return m_ctrl->wxControl::Create(parent, id, pos, size,
-                            style,  //remove borders???
-                            validator, name);
+    wxLogTrace(wxTRACE_GStreamer, wxT("gst_finish_callback"));
+    wxMediaEvent event(wxEVT_MEDIA_FINISHED);
+    be->m_eventHandler->AddPendingEvent(event);
+}
 }
 
 }
 
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend::TransCapsToVideoSize
+//-----------------------------------------------------------------------------
+// "error" from m_playbin/GST_MESSAGE_ERROR
 //
 //
-// Gets the size of our video (in wxSize) from a GstPad
-//---------------------------------------------------------------------------
-bool wxGStreamerMediaBackend::TransCapsToVideoSize(wxGStreamerMediaBackend* be, GstPad* pad)
+// Called by gstreamer when an error is encountered playing the media -
+// We call wxLogTrace in addition wxLogSysError so that we can get it
+// on the command line as well for those who want extra traces.
+//-----------------------------------------------------------------------------
+extern "C" {
+static void gst_error_callback(GstElement *play,
+                               GstElement *src,
+                               GError     *err,
+                               gchar      *debug,
+                               wxGStreamerMediaBackend* be)
 {
 {
-    const GstCaps* caps = GST_PAD_CAPS (pad);
-    if(caps)
-    {
-
-        const GstStructure *s;
-        s = gst_caps_get_structure (caps, 0);
-        wxASSERT(s);
-
-        gst_structure_get_int (s, "width", &be->m_videoSize.x);
-        gst_structure_get_int (s, "height", &be->m_videoSize.y);
-
-        wxLogDebug(wxT("Native video size: [%i,%i]"), be->m_videoSize.x, be->m_videoSize.y);
-
-        const GValue *par;
-        par = gst_structure_get_value (s, "pixel-aspect-ratio");
-
-        if (par)
-        {
-            int num = gst_value_get_fraction_numerator (par),
-                den = gst_value_get_fraction_denominator (par);
-
-            //TODO: maybe better fraction normalization...
-            if (num > den)
-                be->m_videoSize.x = (int) ((float) num * be->m_videoSize.x / den);
-            else
-                be->m_videoSize.y = (int) ((float) den * be->m_videoSize.y / num);
-        }
-
-        wxLogDebug(wxT("Adjusted video size: [%i,%i]"), be->m_videoSize.x, be->m_videoSize.y);
-
-        be->PostRecalcSize();
-        return true;
-    }//end if caps
-
-    return false;
+    wxString sError;
+    sError.Printf(wxT("gst_error_callback\n")
+                  wxT("Error Message:%s\nDebug:%s\n"),
+                  (const wxChar*)wxConvUTF8.cMB2WX(err->message),
+                  (const wxChar*)wxConvUTF8.cMB2WX(debug));
+    wxLogTrace(wxTRACE_GStreamer, sError);
+    wxLogSysError(sError);
+}
 }
 
 }
 
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend::PostRecalcSize
+//-----------------------------------------------------------------------------
+// "notify::caps" from the videopad inside "stream-info" of m_playbin
+//
+// Called by gstreamer when the video caps for the media is ready - currently
+// we use the caps to get the natural size of the video
 //
 //
-// Forces parent to recalc its layout if it has sizers to update
-// to the new video size
-//---------------------------------------------------------------------------
-void wxGStreamerMediaBackend::PostRecalcSize()
+// (Undocumented?)
+//-----------------------------------------------------------------------------
+extern "C" {
+static void gst_notify_caps_callback(GstPad* pad,
+                                     GParamSpec* pspec,
+                                     wxGStreamerMediaBackend* be)
 {
 {
-        m_ctrl->InvalidateBestSize();
-        m_ctrl->GetParent()->Layout();
-        m_ctrl->GetParent()->Refresh();
-        m_ctrl->GetParent()->Update();
-        m_ctrl->SetSize(m_ctrl->GetSize());
+    wxLogTrace(wxTRACE_GStreamer, wxT("gst_notify_caps_callback"));
+    be->QueryVideoSizeFromPad(pad);
+}
 }
 
 }
 
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend::OnFinish
+//-----------------------------------------------------------------------------
+// "notify::stream-info" from m_playbin
+//
+// Run through the stuff in "stream-info" of m_playbin for a valid
+// video pad, and then attempt to query the video size from it - if not
+// set up an event to do so when ready.
 //
 //
-// Called by gstreamer when the media is done playing
+// Currently unused - now we just query it directly using
+// QueryVideoSizeFromElement.
 //
 //
-// 1) Send a wxEVT_MEDIA_STOP to the control
-// 2) If veteod, break out
-// 3) really stop the media
-// 4) Send a wxEVT_MEDIA_FINISHED to the control
-//---------------------------------------------------------------------------
-void wxGStreamerMediaBackend::OnFinish(GstElement *play, gpointer    data)
+// (Undocumented?)
+//-----------------------------------------------------------------------------
+#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10
+extern "C" {
+static void gst_notify_stream_info_callback(GstElement* element,
+                                            GParamSpec* pspec,
+                                            wxGStreamerMediaBackend* be)
 {
 {
-    wxGStreamerMediaBackend* m_parent = (wxGStreamerMediaBackend*) data;
-
-    wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
-                        m_parent->m_ctrl->GetId());
-    m_parent->m_ctrl->ProcessEvent(theEvent);
+    wxLogTrace(wxTRACE_GStreamer, wxT("gst_notify_stream_info_callback"));
+    be->QueryVideoSizeFromElement(be->m_playbin);
+}
+}
+#endif
 
 
-    if(theEvent.IsAllowed())
+//-----------------------------------------------------------------------------
+// "desired-size-changed" from m_xoverlay
+//
+// 0.8-specific this provides us with the video size when it changes -
+// even though we get the caps as well this seems to come before the
+// caps notification does...
+//
+// Note it will return 16,16 for an early-bird value or for audio
+//-----------------------------------------------------------------------------
+#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR < 10
+extern "C" {
+static void gst_desired_size_changed_callback(GstElement * play,
+                                              guint width, guint height,
+                                              wxGStreamerMediaBackend* be)
+{
+    if(!(width == 16 && height == 16))
     {
     {
-        bool bOk = m_parent->Stop();
-        wxASSERT(bOk);
-
-        //send the event to our child
-        wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
-                            m_parent->m_ctrl->GetId());
-        m_parent->m_ctrl->ProcessEvent(theEvent);
+        be->m_videoSize.x = width;
+        be->m_videoSize.y = height;
     }
     }
+    else
+        be->QueryVideoSizeFromElement(be->m_playbin);
+}
 }
 }
+#endif
 
 
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend::OnError
+//-----------------------------------------------------------------------------
+// gst_bus_async_callback [static]
+// gst_bus_sync_callback [static]
 //
 //
-// Called by gstreamer when an error is encountered playing the media
+// Called by m_playbin for notifications such as end-of-stream in 0.10 -
+// in previous versions g_signal notifications were used. Because everything
+// in centered in one switch statement though it reminds one of old WinAPI
+// stuff.
 //
 //
-// TODO: Make this better - maybe some more intelligent wxLog stuff
-//---------------------------------------------------------------------------
-void wxGStreamerMediaBackend::OnError(GstElement *play,
-    GstElement *src,
-    GError     *err,
-    gchar      *debug,
-    gpointer    data)
+// gst_bus_sync_callback is that sync version that is called on the main GUI
+// thread before the async version that we use to set the xwindow id of the
+// XOverlay (NB: This isn't currently used - see CreateControl()).
+//-----------------------------------------------------------------------------
+#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10
+extern "C" {
+static gboolean gst_bus_async_callback(GstBus* bus,
+                                       GstMessage* message,
+                                       wxGStreamerMediaBackend* be)
 {
 {
-    wxLogSysError(
-        wxString::Format(
-            wxT("Error in wxMediaCtrl!\nError Message:%s\nDebug:%s\n"),
-            (const wxChar*)wxConvUTF8.cMB2WX(err->message),
-            (const wxChar*)wxConvUTF8.cMB2WX(debug)
-                        )
-                 );
-}
+    if(((GstElement*)GST_MESSAGE_SRC(message)) != be->m_playbin)
+        return TRUE;
+    if(be->m_asynclock.TryLock() != wxMUTEX_NO_ERROR)
+        return TRUE;
 
 
+    switch(GST_MESSAGE_TYPE(message))
+    {
+        case GST_MESSAGE_STATE_CHANGED:
+        {
+            GstState oldstate, newstate, pendingstate;
+            gst_message_parse_state_changed(message, &oldstate,
+                                            &newstate, &pendingstate);
+            be->HandleStateChange(oldstate, newstate);
+            break;
+        }
+        case GST_MESSAGE_EOS:
+        {
+            gst_finish_callback(NULL, be);
+            break;
+        }
+        case GST_MESSAGE_ERROR:
+        {
+            GError* error;
+            gchar* debug;
+            gst_message_parse_error(message, &error, &debug);
+            gst_error_callback(NULL, NULL, error, debug, be);
+            break;
+        }
+        default:
+            break;
+    }
 
 
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend::Load (File version)
-//
-// Just calls the URI version
-//---------------------------------------------------------------------------
-bool wxGStreamerMediaBackend::Load(const wxString& fileName)
+    be->m_asynclock.Unlock();
+    return FALSE; // remove the message from Z queue
+}
+
+static GstBusSyncReply gst_bus_sync_callback(GstBus* bus,
+                                             GstMessage* message,
+                                             wxGStreamerMediaBackend* be)
 {
 {
-    return Load(
-                    wxURI(
-                            wxString( wxT("file://") ) + fileName
-                         )
-               );
+    // Pass a non-xwindowid-setting event on to the async handler where it
+    // belongs
+    if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT ||
+        !gst_structure_has_name (message->structure, "prepare-xwindow-id"))
+    {
+        //
+        // NB: Unfortunately, the async callback can be quite
+        // buggy at times and often doesn't get called at all,
+        // so here we are processing it right here in the calling
+        // thread instead of the GUI one...
+        //
+        if(gst_bus_async_callback(bus, message, be))
+            return GST_BUS_PASS;
+        else
+            return GST_BUS_DROP;
+    }
+
+    wxLogTrace(wxTRACE_GStreamer, wxT("Got prepare-xwindow-id"));
+    be->SetupXOverlay();
+    return GST_BUS_DROP; // We handled this message - drop from the queue
+}
 }
 }
+#endif
 
 
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend::OnVideoCapsReady
+//-----------------------------------------------------------------------------
+//
+// Private (although not in the C++ sense)  methods
 //
 //
-// Called by gstreamer when the video caps for the media is ready
-//---------------------------------------------------------------------------
-void wxGStreamerMediaBackend::OnVideoCapsReady(GstPad* pad, GParamSpec* pspec, gpointer data)
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::HandleStateChange
+//
+// Handles a state change event from our C Callback for "state-change" or
+// the async queue in 0.10. (Mostly this is here to avoid locking the
+// the mutex twice...)
+//-----------------------------------------------------------------------------
+void wxGStreamerMediaBackend::HandleStateChange(GstElementState oldstate,
+                                                GstElementState newstate)
 {
 {
-    wxGStreamerMediaBackend::TransCapsToVideoSize((wxGStreamerMediaBackend*) data, pad);
+    switch(newstate)
+    {
+        case GST_STATE_PLAYING:
+            wxLogTrace(wxTRACE_GStreamer, wxT("Play event"));
+            QueuePlayEvent();
+            break;
+        case GST_STATE_PAUSED:
+            // For some reason .10 sends a lot of oldstate == newstate
+            // messages - most likely for pending ones - also
+            // !<GST_STATE_PAUSED as we are only concerned
+            if(oldstate < GST_STATE_PAUSED || oldstate == newstate)
+                break;
+            if(wxGStreamerMediaBackend::GetPosition() != 0)
+            {
+                wxLogTrace(wxTRACE_GStreamer, wxT("Pause event"));
+                QueuePauseEvent();
+            }
+            else
+            {
+                wxLogTrace(wxTRACE_GStreamer, wxT("Stop event"));
+                QueueStopEvent();
+            }
+            break;
+       default: // GST_STATE_NULL etc.
+            break;
+    }
 }
 
 }
 
-//---------------------------------------------------------------------------
-// wxGStreamerMediaBackend::Load (URI version)
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::QueryVideoSizeFromElement
 //
 //
-// 1) Stops/Cleanups the previous instance if there is any
-// 2) Creates the gstreamer playbin
-// 3) If there is no playbin bail out
-// 4) Set up the error and end-of-stream callbacks for our player
-// 5) Make our video sink and make sure it supports the x overlay interface
-// 6) Make sure the passed URI is valid and tell playbin to load it
-// 7) Use the xoverlay extension to tell gstreamer to play in our window
-// 8) Get the video size - pause required to set the stream in action
-//---------------------------------------------------------------------------
-bool wxGStreamerMediaBackend::Load(const wxURI& location)
+// Run through the stuff in "stream-info" of element for a valid
+// video pad, and then attempt to query the video size from it - if not
+// set up an event to do so when ready. Return true
+// if we got a valid video pad.
+//-----------------------------------------------------------------------------
+bool wxGStreamerMediaBackend::QueryVideoSizeFromElement(GstElement* element)
 {
 {
-    //1
-    Cleanup();
-
-    //2
-    m_player    = gst_element_factory_make ("playbin", "play");
+    const GList *list = NULL;
+    g_object_get (G_OBJECT (element), "stream-info", &list, NULL);
 
 
-    //3
-    if (!m_player)
-        return false;
+    for ( ; list != NULL; list = list->next)
+    {
+        GObject *info = (GObject *) list->data;
+        gint type;
+        GParamSpec *pspec;
+        GEnumValue *val;
+        GstPad *pad = NULL;
 
 
-    //4
-    g_signal_connect (m_player, "eos", G_CALLBACK (OnFinish), this);
-    g_signal_connect (m_player, "error", G_CALLBACK (OnError), this);
+        g_object_get (info, "type", &type, NULL);
+        pspec = g_object_class_find_property (
+                        G_OBJECT_GET_CLASS (info), "type");
+        val = g_enum_get_value (G_PARAM_SPEC_ENUM (pspec)->enum_class, type);
 
 
-    //5
-    GstElement* overlay = NULL;
-    GstElement* videosink;
+        if (!strncasecmp(val->value_name, "video", 5) ||
+            !strncmp(val->value_name, "GST_STREAM_TYPE_VIDEO", 21))
+        {
+            // Newer gstreamer 0.8+ plugins are SUPPOSED to have "object"...
+            // but a lot of old plugins still use "pad" :)
+            pspec = g_object_class_find_property (
+                        G_OBJECT_GET_CLASS (info), "object");
 
 
-#if defined(__WXGTK__) && wxUSE_DYNLIB_CLASS
+            if (!pspec)
+                g_object_get (info, "pad", &pad, NULL);
+            else
+                g_object_get (info, "object", &pad, NULL);
 
 
-    //use gnome-specific gstreamer extensions
-    //if synthisis (?) file not found, it
-    //spits out a warning and uses ximagesink
-    wxDynamicLibrary gstgconf;
-    if(gstgconf.Load(gstgconf.CanonicalizeName(wxT("gstgconf-0.8"))))
-    {
-        typedef GstElement* (*LPgst_gconf_get_default_video_sink) (void);
-        LPgst_gconf_get_default_video_sink pGst_gconf_get_default_video_sink =
-        (LPgst_gconf_get_default_video_sink)
-            gstgconf.GetSymbol(wxT("gst_gconf_get_default_video_sink"));
+#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR <= 8
+            // Killed in 0.9, presumely because events and such
+            // should be pushed on pads regardless of whether they
+            // are currently linked
+            pad = (GstPad *) GST_PAD_REALIZE (pad);
+            wxASSERT(pad);
+#endif
 
 
-        if (pGst_gconf_get_default_video_sink)
-        {
-            videosink = (*pGst_gconf_get_default_video_sink) ();
-            wxASSERT( GST_IS_BIN(videosink) );
-            overlay = gst_bin_get_by_interface (GST_BIN (videosink),
-                                            GST_TYPE_X_OVERLAY);
-        }
+            if(!QueryVideoSizeFromPad(pad))
+            {
+                // wait for those caps to get ready
+                g_signal_connect(
+                pad,
+                "notify::caps",
+                G_CALLBACK(gst_notify_caps_callback),
+                this);
+            }
+            break;
+        }// end if video
+    }// end searching through info list
 
 
-        gstgconf.Detach();
+    // no video (or extremely delayed stream-info)
+    if(list == NULL)
+    {
+        m_videoSize = wxSize(0,0);
+        return false;
     }
 
     }
 
-    if ( ! GST_IS_X_OVERLAY(overlay) )
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::QueryVideoSizeFromPad
+//
+// Gets the size of our video (in wxSize) from a GstPad
+//-----------------------------------------------------------------------------
+bool wxGStreamerMediaBackend::QueryVideoSizeFromPad(GstPad* pad)
+{
+    const GstCaps* caps = GST_PAD_CAPS(pad);
+    if ( caps )
     {
     {
-#endif
-        wxLogDebug(wxT("Could not load Gnome preferences, reverting to xvimagesink for video for gstreamer"));
-        videosink = gst_element_factory_make ("xvimagesink", "videosink");
-        if ( !GST_IS_OBJECT(videosink) )
-            videosink = gst_element_factory_make ("ximagesink", "videosink");
+        const GstStructure *s = gst_caps_get_structure (caps, 0);
+        wxASSERT(s);
 
 
-        overlay = videosink;
+        gst_structure_get_int (s, "width", &m_videoSize.x);
+        gst_structure_get_int (s, "height", &m_videoSize.y);
 
 
-        wxASSERT( GST_IS_X_OVERLAY(overlay) );
-        if ( ! GST_IS_X_OVERLAY(overlay) )
-            return false;
-#if defined(__WXGTK__) && wxUSE_DYNLIB_CLASS
-    }
-#endif
+        const GValue *par;
+        par = gst_structure_get_value (s, "pixel-aspect-ratio");
+
+        if (par)
+        {
+            wxLogTrace(wxTRACE_GStreamer,
+                       wxT("pixel-aspect-ratio found in pad"));
+            int num = par->data[0].v_int,
+                den = par->data[1].v_int;
 
 
-    g_object_set (G_OBJECT (m_player),
-                    "video-sink", videosink,
-//                    "audio-sink", m_audiosink,
-                    NULL);
+            // TODO: maybe better fraction normalization...
+            if (num > den)
+                m_videoSize.x = (int) ((float) num * m_videoSize.x / den);
+            else
+                m_videoSize.y = (int) ((float) den * m_videoSize.y / num);
+        }
 
 
-    //6
-    wxString locstring = location.BuildUnescapedURI();
-    wxASSERT(gst_uri_protocol_is_valid("file"));
-    wxASSERT(gst_uri_is_valid(locstring.mb_str()));
+         wxLogTrace(wxTRACE_GStreamer, wxT("Adjusted video size: [%i,%i]"),
+                     m_videoSize.x, m_videoSize.y);
+        return true;
+    } // end if caps
 
 
-    g_object_set (G_OBJECT (m_player), "uri", (const char*)locstring.mb_str(), NULL);
+    return false; // not ready/massive failure
+}
 
 
-    //7
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::SetupXOverlay
+//
+// Attempts to set the XWindow id of our GstXOverlay to tell it which
+// window to play video in.
+//-----------------------------------------------------------------------------
+void wxGStreamerMediaBackend::SetupXOverlay()
+{
+    // Use the xoverlay extension to tell gstreamer to play in our window
 #ifdef __WXGTK__
     if(!GTK_WIDGET_REALIZED(m_ctrl->m_wxwindow))
     {
 #ifdef __WXGTK__
     if(!GTK_WIDGET_REALIZED(m_ctrl->m_wxwindow))
     {
-        //Not realized yet - set to connect at realization time
+        // Not realized yet - set to connect at realization time
         g_signal_connect (m_ctrl->m_wxwindow,
                           "realize",
         g_signal_connect (m_ctrl->m_wxwindow,
                           "realize",
-                          G_CALLBACK (wxGStreamerMediaBackend::OnGTKRealize),
+                          G_CALLBACK (gtk_window_realize_callback),
                           this);
     }
     else
     {
                           this);
     }
     else
     {
-        wxYield(); //see realize callback...
+        wxYield(); // see realize callback...
         GdkWindow *window = GTK_PIZZA(m_ctrl->m_wxwindow)->bin_window;
         wxASSERT(window);
 #endif
 
         GdkWindow *window = GTK_PIZZA(m_ctrl->m_wxwindow)->bin_window;
         wxASSERT(window);
 #endif
 
-
-    gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(overlay),
+    gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(m_xoverlay),
 #ifdef __WXGTK__
                         GDK_WINDOW_XWINDOW( window )
 #else
 #ifdef __WXGTK__
                         GDK_WINDOW_XWINDOW( window )
 #else
@@ -500,137 +741,536 @@ bool wxGStreamerMediaBackend::Load(const wxURI& location)
                                   );
 
 #ifdef __WXGTK__
                                   );
 
 #ifdef __WXGTK__
-    } //end else block
+    g_signal_connect (m_ctrl->m_wxwindow,
+                        // m_ctrl->m_wxwindow/*m_ctrl->m_widget*/,
+                      "expose_event",
+                      G_CALLBACK(gtk_window_expose_callback), this);
+    } // end if GtkPizza realized
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::SyncStateChange
+//
+// This function is rather complex - basically the idea is that we
+// poll the GstBus of m_playbin until it has reached desiredstate, an error
+// is reached, or there are no more messages left in the GstBus queue.
+//
+// Returns true if there are no messages left in the queue or
+// the current state reaches the disired state.
+//
+// PRECONDITION: Assumes m_asynclock is Lock()ed
+//-----------------------------------------------------------------------------
+#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10
+bool wxGStreamerMediaBackend::SyncStateChange(GstElement* element,
+                                              GstElementState desiredstate,
+                                              gint64 llTimeout)
+{
+    GstBus* bus = gst_element_get_bus(element);
+    GstMessage* message;
+    bool bBreak = false,
+         bSuccess = false;
+    gint64 llTimeWaited = 0;
+
+    do
+    {
+#if 1
+        // NB: The GStreamer gst_bus_poll is unfortunately broken and
+        // throws silly critical internal errors (for instance
+        // "message != NULL" when the whole point of it is to
+        // poll for the message in the first place!) so we implement
+        // our own "waiting mechinism"
+        if(gst_bus_have_pending(bus) == FALSE)
+        {
+            if(llTimeWaited >= llTimeout)
+                return true; // Reached timeout... assume success
+            llTimeWaited += 10*GST_MSECOND;
+            wxMilliSleep(10);
+            continue;
+        }
+
+        message = gst_bus_pop(bus);
+#else
+        message = gst_bus_poll(bus, (GstMessageType)
+                           (GST_MESSAGE_STATE_CHANGED |
+                            GST_MESSAGE_ERROR |
+                            GST_MESSAGE_EOS), llTimeout);
+        if(!message)
+            return true;
 #endif
 #endif
+        if(((GstElement*)GST_MESSAGE_SRC(message)) == element)
+        {
+            switch(GST_MESSAGE_TYPE(message))
+            {
+                case GST_MESSAGE_STATE_CHANGED:
+                {
+                    GstState oldstate, newstate, pendingstate;
+                    gst_message_parse_state_changed(message, &oldstate,
+                                                    &newstate, &pendingstate);
+                    if(newstate == desiredstate)
+                    {
+                        bSuccess = bBreak = true;
+                    }
+                    break;
+                }
+                case GST_MESSAGE_ERROR:
+                {
+                    GError* error;
+                    gchar* debug;
+                    gst_message_parse_error(message, &error, &debug);
+                    gst_error_callback(NULL, NULL, error, debug, this);
+                    bBreak = true;
+                    break;
+                }
+                case GST_MESSAGE_EOS:
+                    wxLogSysError(wxT("Reached end of stream prematurely"));
+                    bBreak = true;
+                    break;
+                default:
+                    break; // not handled
+            }
+        }
+
+        gst_message_unref(message);
+    }while(!bBreak);
 
 
-    //8
-    int nResult = gst_element_set_state (m_player, GST_STATE_PAUSED);
-    if(nResult != GST_STATE_SUCCESS)
+    return bSuccess;
+}
+#else // 0.8 implementation
+bool wxGStreamerMediaBackend::SyncStateChange(GstElement* element,
+                                              GstElementState desiredstate,
+                                              gint64 llTimeout)
+{
+    gint64 llTimeWaited = 0;
+    while(GST_STATE(element) != desiredstate)
     {
     {
-        wxLogDebug(wxT("Could not set initial state to paused!"));
+        if(llTimeWaited >= llTimeout)
+            break;
+        llTimeWaited += 10*GST_MSECOND;
+        wxMilliSleep(10);
+    }
+
+    return llTimeWaited != llTimeout;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::TryAudioSink
+// wxGStreamerMediaBackend::TryVideoSink
+//
+// Uses various means to determine whether a passed in video/audio sink
+// if suitable for us - if it is not we return false and unref the
+// inappropriate sink.
+//-----------------------------------------------------------------------------
+bool wxGStreamerMediaBackend::TryAudioSink(GstElement* audiosink)
+{
+    if( !GST_IS_ELEMENT(audiosink) )
+    {
+        if(G_IS_OBJECT(audiosink))
+            g_object_unref(audiosink);
         return false;
     }
 
         return false;
     }
 
-    const GList *list = NULL;
-    g_object_get (G_OBJECT (m_player), "stream-info", &list, NULL);
+    return true;
+}
 
 
-    bool bVideoFound = false;
+bool wxGStreamerMediaBackend::TryVideoSink(GstElement* videosink)
+{
+    // Check if the video sink either is an xoverlay or might contain one...
+    if( !GST_IS_BIN(videosink) && !GST_IS_X_OVERLAY(videosink) )
+    {
+        if(G_IS_OBJECT(videosink))
+            g_object_unref(videosink);
+        return false;
+    }
 
 
-    for ( ; list != NULL; list = list->next)
+    // Make our video sink and make sure it supports the x overlay interface
+    // the x overlay enables us to put the video in our control window
+    // (i.e. we NEED it!) - also connect to the natural video size change event
+    if( GST_IS_BIN(videosink) )
+        m_xoverlay = (GstXOverlay*)
+                        gst_bin_get_by_interface (GST_BIN (videosink),
+                                                  GST_TYPE_X_OVERLAY);
+    else
+        m_xoverlay = (GstXOverlay*) videosink;
+
+    if ( !GST_IS_X_OVERLAY(m_xoverlay) )
     {
     {
-        GObject *info = (GObject *) list->data;
-        gint type;
-        GParamSpec *pspec;
-        GEnumValue *val;
-        GstPad *pad = NULL;
+        g_object_unref(videosink);
+        return false;
+    }
 
 
-        g_object_get (info, "type", &type, NULL);
-        pspec = g_object_class_find_property (
-                        G_OBJECT_GET_CLASS (info), "type");
-        val = g_enum_get_value (G_PARAM_SPEC_ENUM (pspec)->enum_class, type);
+    return true;
+}
 
 
-        if (strstr (val->value_name, "VIDEO"))
-        {
-            //Newer gstreamer 0.8+ is SUPPOSED to have "object"...
-            //but a lot of old plugins still use "pad" :)
-            pspec = g_object_class_find_property (
-                        G_OBJECT_GET_CLASS (info), "object");
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaEventHandler::OnMediaFinish
+//
+// Called when the media is about to stop
+//-----------------------------------------------------------------------------
+void wxGStreamerMediaEventHandler::OnMediaFinish(wxMediaEvent& event)
+{
+    // (RN - I have no idea why I thought this was good behaviour....
+    // maybe it made sense for streaming/nonseeking data but
+    // generally it seems like a really bad idea) -
+    if(m_be->SendStopEvent())
+    {
+        // Stop the media (we need to set it back to paused
+        // so that people can get the duration et al.
+        // and send the finish event (luckily we can "Sync" it out... LOL!)
+        // (We don't check return values here because we can't really do
+        //  anything...)
+        wxMutexLocker lock(m_be->m_asynclock);
+
+        // Set element to ready+sync it
+        gst_element_set_state (m_be->m_playbin, GST_STATE_READY);
+        m_be->SyncStateChange(m_be->m_playbin, GST_STATE_READY);
+
+        // Now set it to paused + update pause pos to 0 and
+        // Sync that as well (note that we don't call Stop() here
+        // due to mutex issues)
+        gst_element_set_state (m_be->m_playbin, GST_STATE_PAUSED);
+        m_be->SyncStateChange(m_be->m_playbin, GST_STATE_PAUSED);
+        m_be->m_llPausedPos = 0;
+
+        // Finally, queue the finish event
+        m_be->QueueFinishEvent();
+    }
+}
 
 
-            if (!pspec)
-                g_object_get (info, "pad", &pad, NULL);
-            else
-                g_object_get (info, "object", &pad, NULL);
+//-----------------------------------------------------------------------------
+//
+// Public methods
+//
+//-----------------------------------------------------------------------------
 
 
-            pad = (GstPad *) GST_PAD_REALIZE (pad);
-            wxASSERT(pad);
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend Constructor
+//
+// Sets m_playbin to NULL signifying we havn't loaded anything yet
+//-----------------------------------------------------------------------------
+wxGStreamerMediaBackend::wxGStreamerMediaBackend()
+    : m_playbin(NULL)
+{
+}
+
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend Destructor
+//
+// Stops/cleans up memory
+//
+// NB: This could trigger a critical warning but doing a SyncStateChange
+//     here is just going to slow down quitting of the app, which is bad.
+//-----------------------------------------------------------------------------
+wxGStreamerMediaBackend::~wxGStreamerMediaBackend()
+{
+    // Dispose of the main player and related objects
+    if(m_playbin)
+    {
+        wxASSERT( GST_IS_OBJECT(m_playbin) );
+        gst_element_set_state (m_playbin, GST_STATE_NULL);
+        gst_object_unref (GST_OBJECT (m_playbin));
+        delete m_eventHandler;
+    }
+}
+
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::CreateControl
+//
+// Initializes GStreamer and creates the wx side of our media control
+//-----------------------------------------------------------------------------
+bool wxGStreamerMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
+                                wxWindowID id,
+                                const wxPoint& pos,
+                                const wxSize& size,
+                                long style,
+                                const wxValidator& validator,
+                                const wxString& name)
+{
+    //
+    //init gstreamer
+    //
+    gst_init(&wxTheApp->argc, &wxTheApp->argv);
+
+    //
+    // wxControl creation
+    //
+    m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
+
+#ifdef __WXGTK__
+    // We handle our own GTK expose events
+    m_ctrl->m_noExpose = TRUE;
+#endif
+
+    if( !m_ctrl->wxControl::Create(parent, id, pos, size,
+                            style,  // TODO: remove borders???
+                            validator, name) )
+    {
+        wxFAIL_MSG(wxT("Could not create wxControl!!!"));
+        return false;
+    }
+
+#ifdef __WXGTK__
+    // Turn off double-buffering so that
+    // so it doesn't draw over the video and cause sporadic
+    // disappearances of the video
+    gtk_widget_set_double_buffered(m_ctrl->m_wxwindow, FALSE);
+
+    // Tell GtkPizza not to clear the background
+    gtk_pizza_set_clear(GTK_PIZZA(m_ctrl->m_wxwindow), FALSE);
+#endif
+
+    // don't erase the background of our control window
+    // so that resizing is a bit smoother
+    m_ctrl->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
+
+    // Create our playbin object
+    m_playbin = gst_element_factory_make ("playbin", "play");
+    if (!GST_IS_ELEMENT(m_playbin))
+        {
+        if(G_IS_OBJECT(m_playbin))
+            g_object_unref(m_playbin);
+        wxLogSysError(wxT("Got an invalid playbin"));
+        return false;
+        }
 
 
-            if(!wxGStreamerMediaBackend::TransCapsToVideoSize(this, pad));
+#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR < 10
+    // Connect the glib events/callbacks we want to our playbin
+    g_signal_connect(m_playbin, "eos",
+                     G_CALLBACK(gst_finish_callback), this);
+    g_signal_connect(m_playbin, "error",
+                     G_CALLBACK(gst_error_callback), this);
+    g_signal_connect(m_playbin, "state-change",
+                     G_CALLBACK(gst_state_change_callback), this);
+#else
+    // GStreamer 0.10+ uses GstBus for this now, connect to the sync
+    // handler as well so we can set the X window id of our xoverlay
+    gst_bus_add_watch (gst_element_get_bus(m_playbin),
+                       (GstBusFunc) gst_bus_async_callback, this);
+    gst_bus_set_sync_handler(gst_element_get_bus(m_playbin),
+                             (GstBusSyncHandler) gst_bus_sync_callback, this);
+    g_signal_connect(m_playbin, "notify::stream-info",
+                     G_CALLBACK(gst_notify_stream_info_callback), this);
+#endif
+
+    // Get the audio sink
+    GstElement* audiosink = gst_gconf_get_default_audio_sink();
+    if( !TryAudioSink(audiosink) )
+    {
+        // fallback to autodetection, then alsa, then oss as a stopgap
+        audiosink = gst_element_factory_make ("autoaudiosink", "audio-sink");
+        if( !TryAudioSink(audiosink) )
+        {
+            audiosink = gst_element_factory_make ("alsasink", "alsa-output");
+            if( !TryAudioSink(audiosink) )
             {
             {
-                //wait for those caps to get ready
-                g_signal_connect(
-                pad,
-                "notify::caps",
-                G_CALLBACK(wxGStreamerMediaBackend::OnVideoCapsReady),
-                this);
+                audiosink = gst_element_factory_make ("osssink", "play_audio");
+                if( !TryAudioSink(audiosink) )
+                {
+                    wxLogSysError(wxT("Could not find a valid audiosink"));
+    return false;
+                }
             }
             }
+        }
+    }
 
 
-            bVideoFound = true;
-            break;
-        }//end if video
-        else
+    // Setup video sink - first try gconf, then auto, then xvimage and
+    // then finally plain ximage
+    GstElement* videosink = gst_gconf_get_default_video_sink();
+    if( !TryVideoSink(videosink) )
+    {
+        videosink = gst_element_factory_make ("autovideosink", "video-sink");
+        if( !TryVideoSink(videosink) )
         {
         {
-            m_videoSize = wxSize(0,0);
-            PostRecalcSize();
+            videosink = gst_element_factory_make ("xvimagesink", "video-sink");
+            if( !TryVideoSink(videosink) )
+            {
+                // finally, do a final fallback to ximagesink
+                videosink =
+                    gst_element_factory_make ("ximagesink", "video-sink");
+                if( !TryVideoSink(videosink) )
+                {
+                    g_object_unref(audiosink);
+                    wxLogSysError(wxT("Could not find a suitable video sink"));
+                    return false;
+    }
+            }
         }
         }
-    }//end searching through info list
+    }
+
+#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR < 10
+    // Not on 0.10... called when video size changes
+    g_signal_connect(m_xoverlay, "desired-size-changed",
+                     G_CALLBACK(gst_desired_size_changed_callback), this);
+#endif
+    // Tell GStreamer which window to draw to in 0.8 - 0.10
+    // sometimes needs this too...
+    SetupXOverlay();
+
+    // Now that we know (or, rather think) our video and audio sink
+    // are valid set our playbin to use them
+    g_object_set (G_OBJECT (m_playbin),
+                  "video-sink", videosink,
+                  "audio-sink", audiosink,
+                   NULL);
+
+    m_eventHandler = new wxGStreamerMediaEventHandler(this);
+    return true;
+}
 
 
-    if(!bVideoFound)
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::Load (File version)
+//
+// Just calls the URI version
+//-----------------------------------------------------------------------------
+bool wxGStreamerMediaBackend::Load(const wxString& fileName)
+{
+    return Load(
+                    wxURI(
+                            wxString( wxT("file://") ) + fileName
+                         )
+               );
+}
+
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::Load (URI version)
+//
+// Loads the media
+// 1) Reset member variables and set playbin back to ready state
+// 2) Check URI for validity and then tell the playbin to load it
+// 3) Set the playbin to the pause state
+//
+// NB: Even after this function is over with we probably don't have the
+// video size or duration - no amount of clever hacking is going to get
+// around that, unfortunately.
+//-----------------------------------------------------------------------------
+bool wxGStreamerMediaBackend::Load(const wxURI& location)
+{
+    wxMutexLocker lock(m_asynclock); // lock state events and async callbacks
+
+    // Reset positions & rate
+    m_llPausedPos = 0;
+    m_dRate = 1.0;
+    m_videoSize = wxSize(0,0);
+
+    // Set playbin to ready to stop the current media...
+    if( gst_element_set_state (m_playbin,
+                               GST_STATE_READY) == GST_STATE_FAILURE ||
+        !SyncStateChange(m_playbin, GST_STATE_READY))
     {
     {
-        wxLogDebug(wxT("No video found for gstreamer stream"));
+        wxLogSysError(wxT("wxGStreamerMediaBackend::Load - ")
+                      wxT("Could not set initial state to ready"));
+            return false;
     }
     }
-    m_nPausedPos = 0;
 
 
-    //send loaded event
-    wxMediaEvent theEvent(wxEVT_MEDIA_LOADED,
-                            m_ctrl->GetId());
-    m_ctrl->AddPendingEvent(theEvent);
+    // Make sure the passed URI is valid and tell playbin to load it
+    // non-file uris are encoded
+    wxString locstring;
+    if(location.GetScheme().CmpNoCase(wxT("file")))
+        locstring = location.BuildUnescapedURI();
+    else
+        locstring = location.BuildURI();
 
 
+    wxASSERT(gst_uri_protocol_is_valid("file"));
+    wxASSERT(gst_uri_is_valid(locstring.mb_str()));
+
+    g_object_set (G_OBJECT (m_playbin), "uri",
+                  (const char*)locstring.mb_str(), NULL);
+
+    // Try to pause media as gstreamer won't let us query attributes
+    // such as video size unless it is paused or playing
+    if( gst_element_set_state (m_playbin,
+                               GST_STATE_PAUSED) == GST_STATE_FAILURE ||
+        !SyncStateChange(m_playbin, GST_STATE_PAUSED))
+    {
+        return false; // no real error message needed here as this is
+                      // generic failure 99% of the time (i.e. no
+                      // source etc.) and has an error message
+    }
+
+
+    NotifyMovieLoaded(); // Notify the user - all we can do for now
     return true;
 }
 
     return true;
 }
 
-//---------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
 // wxGStreamerMediaBackend::Play
 //
 // Sets the stream to a playing state
 // wxGStreamerMediaBackend::Play
 //
 // Sets the stream to a playing state
-//---------------------------------------------------------------------------
+//
+// THREAD-UNSAFE in 0.8, maybe in 0.10 as well
+//-----------------------------------------------------------------------------
 bool wxGStreamerMediaBackend::Play()
 {
 bool wxGStreamerMediaBackend::Play()
 {
-    if (gst_element_set_state (m_player, GST_STATE_PLAYING)
-            != GST_STATE_SUCCESS)
+    if (gst_element_set_state (m_playbin,
+                               GST_STATE_PLAYING) == GST_STATE_FAILURE)
         return false;
     return true;
 }
 
         return false;
     return true;
 }
 
-//---------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // wxGStreamerMediaBackend::Pause
 //
 // Marks where we paused and pauses the stream
 // wxGStreamerMediaBackend::Pause
 //
 // Marks where we paused and pauses the stream
-//---------------------------------------------------------------------------
+//
+// THREAD-UNSAFE in 0.8, maybe in 0.10 as well
+//-----------------------------------------------------------------------------
 bool wxGStreamerMediaBackend::Pause()
 {
 bool wxGStreamerMediaBackend::Pause()
 {
-    m_nPausedPos = GetPosition();
-    if (gst_element_set_state (m_player, GST_STATE_PAUSED)
-            != GST_STATE_SUCCESS)
+    m_llPausedPos = wxGStreamerMediaBackend::GetPosition();
+    if (gst_element_set_state (m_playbin,
+                               GST_STATE_PAUSED) == GST_STATE_FAILURE)
         return false;
     return true;
 }
 
         return false;
     return true;
 }
 
-//---------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // wxGStreamerMediaBackend::Stop
 //
 // wxGStreamerMediaBackend::Stop
 //
-// Pauses the stream and sets the position to 0
-//---------------------------------------------------------------------------
+// Pauses the stream and sets the position to 0. Note that this is
+// synchronous (!) pausing.
+//
+// Due to the mutex locking this is probably thread-safe actually.
+//-----------------------------------------------------------------------------
 bool wxGStreamerMediaBackend::Stop()
 {
 bool wxGStreamerMediaBackend::Stop()
 {
-    if (gst_element_set_state (m_player,
-                    GST_STATE_PAUSED)    != GST_STATE_SUCCESS)
+    {   // begin state lock
+        wxMutexLocker lock(m_asynclock);
+        if(gst_element_set_state (m_playbin,
+                                  GST_STATE_PAUSED) == GST_STATE_FAILURE ||
+          !SyncStateChange(m_playbin, GST_STATE_PAUSED))
+        {
+            wxLogSysError(wxT("Could not set state to paused for Stop()"));
+            return false;
+        }
+    }   // end state lock
+
+    bool bSeekedOK = wxGStreamerMediaBackend::SetPosition(0);
+
+    if(!bSeekedOK)
+    {
+        wxLogSysError(wxT("Could not seek to initial position in Stop()"));
         return false;
         return false;
-    return wxGStreamerMediaBackend::SetPosition(0);
+    }
+
+    QueueStopEvent(); // Success
+    return true;
 }
 
 }
 
-//---------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // wxGStreamerMediaBackend::GetState
 //
 // wxGStreamerMediaBackend::GetState
 //
-// Gets the state of the stream
-//---------------------------------------------------------------------------
+// Gets the state of the media
+//-----------------------------------------------------------------------------
 wxMediaState wxGStreamerMediaBackend::GetState()
 {
 wxMediaState wxGStreamerMediaBackend::GetState()
 {
-    switch(GST_STATE(m_player))
+    switch(GST_STATE(m_playbin))
     {
         case GST_STATE_PLAYING:
             return wxMEDIASTATE_PLAYING;
         case GST_STATE_PAUSED:
     {
         case GST_STATE_PLAYING:
             return wxMEDIASTATE_PLAYING;
         case GST_STATE_PAUSED:
-            if (m_nPausedPos == 0)
+            if (m_llPausedPos == 0)
                 return wxMEDIASTATE_STOPPED;
             else
                 return wxMEDIASTATE_PAUSED;
                 return wxMEDIASTATE_STOPPED;
             else
                 return wxMEDIASTATE_PAUSED;
@@ -639,94 +1279,128 @@ wxMediaState wxGStreamerMediaBackend::GetState()
     }
 }
 
     }
 }
 
-//---------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // wxGStreamerMediaBackend::GetPosition
 //
 // If paused, returns our marked position - otherwise it queries the
 // GStreamer playbin for the position and returns that
 //
 // wxGStreamerMediaBackend::GetPosition
 //
 // If paused, returns our marked position - otherwise it queries the
 // GStreamer playbin for the position and returns that
 //
-//TODO:
-//TODO: In lue of the last big TODO, when you pause and seek gstreamer
-//TODO: doesn't update the position sometimes, so we need to keep track of whether
-//TODO: we have paused or not and keep track of the time after the pause
-//TODO: and whenever the user seeks while paused
-//TODO:
-//---------------------------------------------------------------------------
+// NB:
+// NB: At least in 0.8, when you pause and seek gstreamer
+// NB: doesn't update the position sometimes, so we need to keep track of
+// NB: whether we have paused or not and keep track of the time after the
+// NB: pause and whenever the user seeks while paused
+// NB:
+// 
+// THREAD-UNSAFE, at least if not paused. Requires media to be at least paused.
+//-----------------------------------------------------------------------------
 wxLongLong wxGStreamerMediaBackend::GetPosition()
 {
     if(GetState() != wxMEDIASTATE_PLAYING)
 wxLongLong wxGStreamerMediaBackend::GetPosition()
 {
     if(GetState() != wxMEDIASTATE_PLAYING)
-        return m_nPausedPos;
+        return m_llPausedPos;
     else
     {
         gint64 pos;
         GstFormat fmtTime = GST_FORMAT_TIME;
 
     else
     {
         gint64 pos;
         GstFormat fmtTime = GST_FORMAT_TIME;
 
-        if (!gst_element_query (m_player, GST_QUERY_POSITION, &fmtTime, &pos))
+        if (!wxGst_element_query_position(m_playbin, &fmtTime, &pos) ||
+            fmtTime != GST_FORMAT_TIME || pos == -1)
             return 0;
         return pos / GST_MSECOND ;
     }
 }
 
             return 0;
         return pos / GST_MSECOND ;
     }
 }
 
-//---------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // wxGStreamerMediaBackend::SetPosition
 //
 // Sets the position of the stream
 // Note that GST_MSECOND is 1000000 (GStreamer uses nanoseconds - so
 // there is 1000000 nanoseconds in a millisecond)
 //
 // wxGStreamerMediaBackend::SetPosition
 //
 // Sets the position of the stream
 // Note that GST_MSECOND is 1000000 (GStreamer uses nanoseconds - so
 // there is 1000000 nanoseconds in a millisecond)
 //
-// If paused marks where we seeked to
-//---------------------------------------------------------------------------
+// If we are paused we update the cached pause position.
+//
+// This is also an exceedingly ugly function due to the three implementations
+// (or, rather two plus one implementation without a seek function).
+//
+// This is asynchronous and thread-safe on both 0.8 and 0.10.
+//
+// NB: This fires both a stop and play event if the media was previously
+// playing... which in some ways makes sense. And yes, this makes the video
+// go all haywire at times - a gstreamer bug...
+//-----------------------------------------------------------------------------
 bool wxGStreamerMediaBackend::SetPosition(wxLongLong where)
 {
 bool wxGStreamerMediaBackend::SetPosition(wxLongLong where)
 {
-    if( gst_element_seek (m_player, (GstSeekType) (GST_SEEK_METHOD_SET |
+#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR == 8 \
+                           && GST_VERSION_MICRO == 0
+    // 0.8.0 has no gst_element_seek according to official docs!!!
+    wxLogSysError(wxT("GStreamer 0.8.0 does not have gst_element_seek")
+                  wxT(" according to official docs"));
+    return false;
+#else // != 0.8.0
+
+#   if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10
+        gst_element_seek (m_playbin, m_dRate, GST_FORMAT_TIME,
+           (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
+                          GST_SEEK_TYPE_SET, where.GetValue() * GST_MSECOND,
+                          GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE );
+#   else
+        // NB: Some gstreamer versions return false basically all the time
+        // here - even totem doesn't bother to check the return value here
+        // so I guess we'll just assume it worked -
+        // TODO: maybe check the gst error callback???
+        gst_element_seek (m_playbin, (GstSeekType) (GST_SEEK_METHOD_SET |
             GST_FORMAT_TIME | GST_SEEK_FLAG_FLUSH),
             GST_FORMAT_TIME | GST_SEEK_FLAG_FLUSH),
-            where.GetValue() * GST_MSECOND ) )
-    {
-        if (GetState() != wxMEDIASTATE_PLAYING)
-            m_nPausedPos = where;
+            where.GetValue() * GST_MSECOND );
+
+#   endif // GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10
 
 
+    {
+        m_llPausedPos = where;
         return true;
     }
         return true;
     }
-
-    return false;
+    return true;
+#endif //== 0.8.0
 }
 
 }
 
-//---------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // wxGStreamerMediaBackend::GetDuration
 //
 // Obtains the total time of our stream
 // wxGStreamerMediaBackend::GetDuration
 //
 // Obtains the total time of our stream
-//---------------------------------------------------------------------------
+// THREAD-UNSAFE, requires media to be paused or playing
+//-----------------------------------------------------------------------------
 wxLongLong wxGStreamerMediaBackend::GetDuration()
 {
     gint64 length;
     GstFormat fmtTime = GST_FORMAT_TIME;
 
 wxLongLong wxGStreamerMediaBackend::GetDuration()
 {
     gint64 length;
     GstFormat fmtTime = GST_FORMAT_TIME;
 
-    if(!gst_element_query(m_player, GST_QUERY_TOTAL, &fmtTime, &length))
+    if(!wxGst_element_query_duration(m_playbin, &fmtTime, &length) ||
+       fmtTime != GST_FORMAT_TIME || length == -1)
         return 0;
     return length / GST_MSECOND ;
 }
 
         return 0;
     return length / GST_MSECOND ;
 }
 
-//---------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // wxGStreamerMediaBackend::Move
 //
 // Called when the window is moved - GStreamer takes care of this
 // for us so nothing is needed
 // wxGStreamerMediaBackend::Move
 //
 // Called when the window is moved - GStreamer takes care of this
 // for us so nothing is needed
-//---------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 void wxGStreamerMediaBackend::Move(int x, int y, int w, int h)
 {
 }
 
 void wxGStreamerMediaBackend::Move(int x, int y, int w, int h)
 {
 }
 
-//---------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // wxGStreamerMediaBackend::GetVideoSize
 //
 // wxGStreamerMediaBackend::GetVideoSize
 //
-// Returns our cached video size from Load/OnVideoCapsReady
-//---------------------------------------------------------------------------
+// Returns our cached video size from Load/gst_notify_caps_callback
+// gst_x_overlay_get_desired_size also does this in 0.8...
+//-----------------------------------------------------------------------------
 wxSize wxGStreamerMediaBackend::GetVideoSize() const
 {
     return m_videoSize;
 }
 
 wxSize wxGStreamerMediaBackend::GetVideoSize() const
 {
     return m_videoSize;
 }
 
-//---------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
 // wxGStreamerMediaBackend::GetPlaybackRate
 // wxGStreamerMediaBackend::SetPlaybackRate
 //
 // wxGStreamerMediaBackend::GetPlaybackRate
 // wxGStreamerMediaBackend::SetPlaybackRate
 //
@@ -745,22 +1419,117 @@ wxSize wxGStreamerMediaBackend::GetVideoSize() const
 //TODO: again cannot do this, so this may not work at all in the end). For
 //TODO: forcing frame/samplerates, see audioscale and videorate. Audioscale is
 //TODO: part of playbin.
 //TODO: again cannot do this, so this may not work at all in the end). For
 //TODO: forcing frame/samplerates, see audioscale and videorate. Audioscale is
 //TODO: part of playbin.
-//---------------------------------------------------------------------------
+//
+// In 0.10 GStreamer has new gst_element_seek API that might
+// support this - and I've got an attempt to do so but it is untested
+// but it would appear to work...
+//-----------------------------------------------------------------------------
 double wxGStreamerMediaBackend::GetPlaybackRate()
 {
 double wxGStreamerMediaBackend::GetPlaybackRate()
 {
-    //not currently supported via playbin
-    return 1.0;
+    return m_dRate; // Could use GST_QUERY_RATE but the API doesn't seem
+                    // final on that yet and there may not be any actual
+                    // plugins that support it...
 }
 
 bool wxGStreamerMediaBackend::SetPlaybackRate(double dRate)
 {
 }
 
 bool wxGStreamerMediaBackend::SetPlaybackRate(double dRate)
 {
-    //not currently supported via playbin
+#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10
+#if 0 // not tested enough
+    if( gst_element_seek (m_playbin, dRate, GST_FORMAT_TIME,
+                 (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT),
+                          GST_SEEK_TYPE_CUR, 0,
+                          GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE ) )
+    {
+        m_dRate = dRate;
+        return true;
+    }
+#endif
+#endif
+
+    // failure
+    return false;
+}
+
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::GetDownloadProgress
+//
+// Not really outwardly possible - have been suggested that one could
+// get the information from the component that "downloads"
+//-----------------------------------------------------------------------------
+wxLongLong wxGStreamerMediaBackend::GetDownloadProgress()
+{
+    return 0;
+}
+
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::GetDownloadTotal
+//
+// TODO: Cache this?
+// NB: The length changes every call for some reason due to
+//     GStreamer implementation issues
+// THREAD-UNSAFE, requires media to be paused or playing
+//-----------------------------------------------------------------------------
+wxLongLong wxGStreamerMediaBackend::GetDownloadTotal()
+{
+    gint64 length;
+    GstFormat fmtBytes = GST_FORMAT_BYTES;
+
+    if (!wxGst_element_query_duration(m_playbin, &fmtBytes, &length) ||
+          fmtBytes != GST_FORMAT_BYTES || length == -1)
+        return 0;
+    return length;
+}
+
+//-----------------------------------------------------------------------------
+// wxGStreamerMediaBackend::SetVolume
+// wxGStreamerMediaBackend::GetVolume
+//
+// Sets/Gets the volume through the playbin object.
+// Note that this requires a relatively recent gst-plugins so we
+// check at runtime to see whether it is available or not otherwise
+// GST spits out an error on the command line
+//-----------------------------------------------------------------------------
+bool wxGStreamerMediaBackend::SetVolume(double dVolume)
+{
+    if(g_object_class_find_property(
+            G_OBJECT_GET_CLASS(G_OBJECT(m_playbin)),
+            "volume") != NULL)
+    {
+        g_object_set(G_OBJECT(m_playbin), "volume", dVolume, NULL);
+        return true;
+    }
+    else
+    {
+        wxLogTrace(wxTRACE_GStreamer,
+            wxT("SetVolume: volume prop not found - 0.8.5 of ")
+            wxT("gst-plugins probably needed"));
     return false;
     return false;
+    }
+}
+
+double wxGStreamerMediaBackend::GetVolume()
+{
+    double dVolume = 1.0;
+
+    if(g_object_class_find_property(
+            G_OBJECT_GET_CLASS(G_OBJECT(m_playbin)),
+            "volume") != NULL)
+    {
+        g_object_get(G_OBJECT(m_playbin), "volume", &dVolume, NULL);
+    }
+    else
+    {
+        wxLogTrace(wxTRACE_GStreamer,
+            wxT("GetVolume: volume prop not found - 0.8.5 of ")
+            wxT("gst-plugins probably needed"));
+    }
+
+    return dVolume;
 }
 
 #endif //wxUSE_GSTREAMER
 
 }
 
 #endif //wxUSE_GSTREAMER
 
-//in source file that contains stuff you don't directly use
+// Force link into main library so this backend can be loaded
 #include "wx/html/forcelnk.h"
 FORCE_LINK_ME(basewxmediabackends)
 
 #include "wx/html/forcelnk.h"
 FORCE_LINK_ME(basewxmediabackends)