]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/mediactrl.cpp
Compilation fix for unix builds with cygwin
[wxWidgets.git] / src / msw / mediactrl.cpp
index 838347354f4d09bb1f73cfde4eb7dc1ce145516d..6d56bfa700df7c41993fc4fc35dbc15760a56644 100644 (file)
@@ -38,6 +38,9 @@
 //---------------------------------------------------------------------------
 #if wxUSE_MEDIACTRL
 
+#include "wx/dcclient.h"
+#include "wx/thread.h"
+
 //---------------------------------------------------------------------------
 // Externals (somewhere in src/msw/app.cpp)
 //---------------------------------------------------------------------------
@@ -67,28 +70,28 @@ extern WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName;
 //  Basically, the way directshow works is that you tell it to render
 //  a file, and it builds and connects a bunch of filters together.
 //
-//  There are many, many ways to do this.  
+//  There are many, many ways to do this.
 //
 //  WAYS TO RENDER A FILE (URLS WORK IN DS ALSO)
 //
 //  1)  Create an instance of IGraphBuilder and call RenderFile on it
 //  2)  Create an instance of IMediaControl and call RenderFile on it
-//  3)  Create an instance of IAMMultiMediaStream, call 
+//  3)  Create an instance of IAMMultiMediaStream, call
 //      IAMMultiMediaStream::AddStream and pass an IDirectDraw instance for
-//      the video, and pass an IDirectSound(Buffer?) instance or use the 
+//      the video, and pass an IDirectSound(Buffer?) instance or use the
 //      default sound renderer, then call RenderFile or RenderMoniker
 //  4)  Create a Moniker instance for the file and create and build
 //      all of the filtergraph manually
 //
 //  Our issue here is that we can't use the default representation of 1 and 2
-//  because the IVideoWindow instance hogs a lot of the useful window 
+//  because the IVideoWindow instance hogs a lot of the useful window
 //  messages such as WM_SETCURSOR.
 //
-//  Solution #1 was to use #3 by creating a seperate IDirectDraw instance 
+//  Solution #1 was to use #3 by creating a seperate IDirectDraw instance
 //  for our window and blitting to that through a thread... unfortunately
 //  the blitting resizing is very low quality and its quite slow.
 //
-//  The current way is to use windowless rendering and have directshow 
+//  The current way is to use windowless rendering and have directshow
 //  do all the DirectDraw-style clipping to our window
 //
 //  ~~~~~~~~~~~~~~AFTER RENDERING THE FILE~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -96,7 +99,7 @@ extern WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName;
 //  When done rendering the file, we need to get several interfaces from
 //  either a IMediaControl or IGraphBuilder instance -
 //
-//  IMediaPosition - we can set the rate with this... we can also get 
+//  IMediaPosition - we can set the rate with this... we can also get
 //  positions and set positions through this with REFTIME (double) instead
 //  of the normal LONGLONG that IAMMultiMediaStream and IMediaControl use
 //
@@ -104,7 +107,7 @@ extern WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName;
 //
 //  Interfaces that we don't use but might be useful one day -
 //
-//  IDirectDrawVideo - you can get this through the IFilter returned 
+//  IDirectDrawVideo - you can get this through the IFilter returned
 //  from L"Video Renderer" filter from FindFilter on the IGraphBuilder.
 //  Through this we can set the IDirectDraw instance DrawShow uses.
 //
@@ -113,7 +116,7 @@ extern WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName;
 //  There are two ways we can do this -
 //  1)  Have a thread compare the current position to the end position
 //  about every 10 milliseconds
-//  2)  Have IMediaSeekingEx send a message to a windowproc or signal a 
+//  2)  Have IMediaSeekingEx send a message to a windowproc or signal a
 //  windows event
 //
 //  Note that we can do these both, I.E. if an IMediaSeekingEx interface
@@ -141,7 +144,7 @@ extern WXDLLIMPEXP_CORE const wxChar *wxCanvasClassName;
 #endif
 //---------------------------------------------------------------------------
 //  IIDS - used by CoCreateInstance and IUnknown::QueryInterface
-//  Dumped from amstream.idl, quartz.idl, direct draw and with some 
+//  Dumped from amstream.idl, quartz.idl, direct draw and with some
 //  confirmation from WINE
 //
 //  Some of these are not used but are kept here for future reference anyway
@@ -206,31 +209,31 @@ typedef struct DDCAPS* LPDDCAPS;
 
 struct DDSURFACEDESC
 {
-    DWORD               dwSize;                 
-    DWORD               dwFlags;                
-    DWORD               dwHeight;               
-    DWORD               dwWidth;                
+    DWORD               dwSize;
+    DWORD               dwFlags;
+    DWORD               dwHeight;
+    DWORD               dwWidth;
     union
     {
-        LONG            lPitch;                 
-        DWORD           dwLinearSize;           
+        LONG            lPitch;
+        DWORD           dwLinearSize;
     };
-    DWORD               dwBackBufferCount;      
+    DWORD               dwBackBufferCount;
     union
     {
-        DWORD           dwMipMapCount;          
-        DWORD           dwZBufferBitDepth;      
-        DWORD           dwRefreshRate;          
+        DWORD           dwMipMapCount;
+        DWORD           dwZBufferBitDepth;
+        DWORD           dwRefreshRate;
     };
-    DWORD               dwAlphaBitDepth;       
-    DWORD               dwReserved;            
-    LPVOID              lpSurface;              
-    DDCOLORKEY          ddckCKDestOverlay;      
-    DDCOLORKEY          ddckCKDestBlt;          
-    DDCOLORKEY          ddckCKSrcOverlay;       
-    DDCOLORKEY          ddckCKSrcBlt;           
-    DDPIXELFORMAT ddpfPixelFormat;        
-    struct DDSCAPS {DWORD dwCaps;} ddsCaps;                
+    DWORD               dwAlphaBitDepth;
+    DWORD               dwReserved;
+    LPVOID              lpSurface;
+    DDCOLORKEY          ddckCKDestOverlay;
+    DDCOLORKEY          ddckCKDestBlt;
+    DDCOLORKEY          ddckCKSrcOverlay;
+    DDCOLORKEY          ddckCKSrcBlt;
+    DDPIXELFORMAT ddpfPixelFormat;
+    struct DDSCAPS {DWORD dwCaps;} ddsCaps;
 };
 
 struct IDirectDrawClipper : public IUnknown
@@ -260,7 +263,7 @@ struct IDirectDrawSurface : public IUnknown
     STDMETHOD(GetClipper)(LPDIRECTDRAWCLIPPER*) PURE;
     STDMETHOD(GetColorKey)(DWORD, LPDDCOLORKEY) PURE;
     STDMETHOD(GetDC)(HDC *) PURE;
-    STDMETHOD(GetFlipStatus)(DWORD) PURE;    
+    STDMETHOD(GetFlipStatus)(DWORD) PURE;
     STDMETHOD(GetOverlayPosition)(LPLONG, LPLONG ) PURE;
     STDMETHOD(GetPalette)(LPDIRECTDRAWPALETTE FAR*) PURE;
     STDMETHOD(GetPixelFormat)(LPDDPIXELFORMAT) PURE;
@@ -273,7 +276,7 @@ struct IDirectDrawSurface : public IUnknown
     STDMETHOD(SetClipper)(LPDIRECTDRAWCLIPPER) PURE;
     STDMETHOD(SetColorKey)(DWORD, LPDDCOLORKEY) PURE;
     STDMETHOD(SetOverlayPosition)(LONG, LONG ) PURE;
-    STDMETHOD(SetPalette)(IUnknown*) PURE; 
+    STDMETHOD(SetPalette)(IUnknown*) PURE;
     STDMETHOD(Unlock)(LPVOID) PURE;
     STDMETHOD(UpdateOverlay)(LPRECT, LPDIRECTDRAWSURFACE,LPRECT,
                                DWORD, struct DDOVERLAYFX*) PURE;
@@ -304,9 +307,9 @@ struct IDirectDraw : public IUnknown
     STDMETHOD(SetDisplayMode)(DWORD, DWORD,DWORD, DWORD, DWORD) PURE;
     STDMETHOD(WaitForVerticalBlank)(DWORD, HANDLE ) PURE;
 };
-    
+
 //---------------------------------------------------------------------------
-//  AMMEDIA COM INTERFACES 
+//  AMMEDIA COM INTERFACES
 //---------------------------------------------------------------------------
 struct IMediaStream;
 struct IMultiMediaStream;
@@ -330,10 +333,10 @@ public:
 struct IMediaStream : public IUnknown
 {
     STDMETHOD(GetMultiMediaStream)(IMultiMediaStream **) PURE;
-    STDMETHOD(GetInformation)(GUID *, int *) PURE;    
+    STDMETHOD(GetInformation)(GUID *, int *) PURE;
     STDMETHOD(SetSameFormat)(IMediaStream *, DWORD) PURE;
     STDMETHOD(AllocateSample)(DWORD, IStreamSample **) PURE;
-    STDMETHOD(CreateSharedSample)(IStreamSample *, DWORD, 
+    STDMETHOD(CreateSharedSample)(IStreamSample *, DWORD,
                                   IStreamSample **) PURE;
     STDMETHOD(SendEndOfStream)(DWORD dwFlags) PURE;
 };
@@ -353,7 +356,7 @@ struct IDirectDrawMediaStream : public IMediaStream
 struct IMultiMediaStream : public IUnknown
 {
     STDMETHOD(GetInformation)(DWORD *, int *) PURE;
-    STDMETHOD(GetMediaStream)(REFGUID, IMediaStream **) PURE;    
+    STDMETHOD(GetMediaStream)(REFGUID, IMediaStream **) PURE;
     STDMETHOD(EnumMediaStreams)(long, IMediaStream **) PURE;
     STDMETHOD(GetState)(int *pCurrentState) PURE;
     STDMETHOD(SetState)(int NewState) PURE;
@@ -368,7 +371,7 @@ struct IAMMultiMediaStream : public IMultiMediaStream
     STDMETHOD(Initialize)(int, DWORD, IUnknown *) PURE;
     STDMETHOD(GetFilterGraph)(IUnknown **) PURE;
     STDMETHOD(GetFilter)(IUnknown **) PURE;
-    STDMETHOD(AddMediaStream)(IUnknown *, const GUID*, DWORD, 
+    STDMETHOD(AddMediaStream)(IUnknown *, const GUID*, DWORD,
                               IMediaStream **) PURE;
     STDMETHOD(OpenFile)(LPCWSTR, DWORD) PURE;
     STDMETHOD(OpenMoniker)(IBindCtx *, IMoniker *, DWORD) PURE;
@@ -446,7 +449,7 @@ struct IVMRWindowlessControl : public IUnknown
     STDMETHOD(GetNativeVideoSize)(LONG *, LONG *, LONG *, LONG *) PURE;
     STDMETHOD(GetMinIdealVideoSize)(LONG *, LONG *) PURE;
     STDMETHOD(GetMaxIdealVideoSize)(LONG *, LONG *) PURE;
-    STDMETHOD(SetVideoPosition)(const LPRECT,const LPRECT) PURE;    
+    STDMETHOD(SetVideoPosition)(const LPRECT,const LPRECT) PURE;
     STDMETHOD(GetVideoPosition)(LPRECT, LPRECT) PURE;
     STDMETHOD(GetAspectRatioMode)(DWORD *) PURE;
     STDMETHOD(SetAspectRatioMode)(DWORD) PURE;
@@ -470,13 +473,13 @@ struct IVMRFilterConfig : public IUnknown
     STDMETHOD(SetRenderingPrefs)(DWORD) PURE;
     STDMETHOD(GetRenderingPrefs)(DWORD *) PURE;
     STDMETHOD(SetRenderingMode)(DWORD) PURE;
-    STDMETHOD(GetRenderingMode)(DWORD *) PURE;  
+    STDMETHOD(GetRenderingMode)(DWORD *) PURE;
 };
-    
+
 typedef IUnknown IBaseFilter;
 typedef IUnknown IPin;
 typedef IUnknown IEnumFilters;
-typedef int AM_MEDIA_TYPE; 
+typedef int AM_MEDIA_TYPE;
 
 struct IFilterGraph : public IUnknown
 {
@@ -518,8 +521,6 @@ class WXDLLIMPEXP_MEDIA wxAMMediaEvtHandler : public wxEvtHandler
 {
 public:
     void OnPaint(wxPaintEvent&);
-    void OnMove(wxMoveEvent&);
-    void OnSize(wxSizeEvent&);
     void OnEraseBackground(wxEraseEvent&);
 };
 
@@ -564,7 +565,7 @@ public:
 
     void Cleanup();
     void OnStop();
-    bool SetWindowlessMode(IGraphBuilder* pGB, 
+    bool SetWindowlessMode(IGraphBuilder* pGB,
                            IVMRWindowlessControl** ppVMC = NULL);
 
     wxControl* m_ctrl;
@@ -578,7 +579,8 @@ public:
     IMediaControl* m_pMC;
     IMediaEvent* m_pME;
     IMediaPosition* m_pMS;
-    
+    bool m_bVideo;
+
     wxAMMediaThread* m_pThread;
 
     wxSize m_bestSize;
@@ -586,6 +588,7 @@ public:
 #ifdef __WXDEBUG__
     HMODULE m_hQuartzDll;
     LPAMGETERRORTEXT m_lpAMGetErrorText;
+    wxString GetErrorString(HRESULT hrdsv);
 #endif
 
     friend class wxAMMediaThread;
@@ -740,7 +743,8 @@ struct TimeRecord {
 
 #define wxDL_METHOD_LOAD( lib, name, success ) \
     pfn_ ## name = (name ## Type) lib.GetSymbol( wxT(#name), &success ); \
-    if (!success) return false;
+    if (!success) { wxLog::EnableLogging(bWasLoggingEnabled); return false; }
+
 
 //Class that utilizes Robert Roeblings Dynamic Library Macros
 class WXDLLIMPEXP_MEDIA wxQuickTimeLibrary
@@ -826,10 +830,15 @@ bool wxQuickTimeLibrary::Initialize()
 {
     m_ok = false;
 
+    bool bWasLoggingEnabled = wxLog::EnableLogging(false);    //Turn off the wxDynamicLibrary logging
+
     if(!m_dll.Load(wxT("qtmlClient.dll")))
+    {
+        wxLog::EnableLogging(bWasLoggingEnabled);
         return false;
+    }
 
-    bool bOk;
+    bool bOk;   //TODO:  Get rid of this, use m_ok instead (not a biggie)
 
     wxDL_METHOD_LOAD( m_dll, StartMovie, bOk );
     wxDL_METHOD_LOAD( m_dll, StopMovie, bOk );
@@ -867,6 +876,7 @@ bool wxQuickTimeLibrary::Initialize()
     wxDL_METHOD_LOAD( m_dll, GetMovieVolume, bOk );
     wxDL_METHOD_LOAD( m_dll, SetMovieVolume, bOk );
 
+    wxLog::EnableLogging(bWasLoggingEnabled);
     m_ok = true;
 
     return true;
@@ -938,42 +948,39 @@ IMPLEMENT_DYNAMIC_CLASS(wxAMMediaBackend, wxMediaBackend);
 // Usual debugging macros
 //---------------------------------------------------------------------------
 #ifdef __WXDEBUG__
-#include "wx/msgdlg.h"
 #define MAX_ERROR_TEXT_LEN 160
-//
-// FIXME : Just use wxASSERT_MSG here instead of msgdlg - but
-// stackwalker still crashes win2k, so do msgdlg for now...
-//
-#define wxAMVERIFY(x) \
-{ \
-    HRESULT hrdsv = (x); \
-    if ( FAILED(hrdsv) ) \
-    { \
-        wxChar szError[MAX_ERROR_TEXT_LEN]; \
-        if( m_lpAMGetErrorText != NULL && \
-           (*m_lpAMGetErrorText)(hrdsv, szError, MAX_ERROR_TEXT_LEN) == 0) \
-        { \
-            wxMessageBox( wxString::Format(wxT("DirectShow error \"%s\" \n")\
-                                         wxT("(numeric %i)\n")\
-                                         wxT("occured at line %i in ") \
-                                         wxT("mediactrl.cpp"), \
-                                         (int)hrdsv, szError, __LINE__) ); \
-            wxASSERT(false);\
-        } \
-        else \
-        { \
-            wxMessageBox( wxString::Format(wxT("Unknown error (%i) ") \
-                                         wxT("occurred at") \
-                                         wxT(" line %i in mediactrl.cpp."), \
-                                         (int)hrdsv, __LINE__) ); \
-            wxASSERT(false);\
-        } \
-    } \
+#include "wx/log.h"             //wxLogDebug et al.
+
+//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 %i)\n")
+                                     wxT("occured at line %i in ")
+                                     wxT("mediactrl.cpp"),
+                                     szError, (int)hrdsv, __LINE__);
+    }
+    else
+    {
+        return wxString::Format(wxT("Unknown error (%i) ")
+                                     wxT("occurred at")
+                                     wxT(" line %i in mediactrl.cpp."),
+                                     (int)hrdsv, __LINE__);
+    }
 }
+
+#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
 
 //---------------------------------------------------------------------------
@@ -986,11 +993,18 @@ IMPLEMENT_DYNAMIC_CLASS(wxAMMediaBackend, wxMediaBackend);
 //
 // Sets m_hNotifyWnd to NULL to signify that we haven't loaded anything yet
 //---------------------------------------------------------------------------
-wxAMMediaBackend::wxAMMediaBackend() : m_state(wxMEDIASTATE_STOPPED),
-m_pVMC(NULL)
-    #ifdef __WXDEBUG__
-    , m_hQuartzDll(NULL)
-    #endif
+wxAMMediaBackend::wxAMMediaBackend()
+                 :m_state(wxMEDIASTATE_STOPPED)
+                 ,m_pVMC(NULL)
+                 ,m_pGB(NULL)
+                 ,m_pBA(NULL)
+                 ,m_pMC(NULL)
+                 ,m_pME(NULL)
+                 ,m_pMS(NULL)
+                 ,m_pThread(NULL)
+#ifdef __WXDEBUG__
+                 ,m_hQuartzDll(NULL)
+#endif
 {
 }
 
@@ -1047,7 +1061,7 @@ bool wxAMMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
 
     //Make sure a valid windowless video mixing interface exists
     IGraphBuilder* pGB;
-    if( CoCreateInstance(CLSID_FilgraphManager, NULL, 
+    if( ::CoCreateInstance(CLSID_FilgraphManager, NULL,
                                   CLSCTX_INPROC_SERVER,
                                   IID_IGraphBuilder, (void**)&pGB) != 0 )
         return false;
@@ -1070,58 +1084,20 @@ bool wxAMMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
                             validator, name) )
         return false;
 
-    m_ctrl = ctrl;
-
-    //
-    // Connect Events
-    //
-    //TODO:  Greg Hazel reports problems with this... but win2k seems fine on mine...
-    //-------------------------------------------------------------------------------
     // My problem with this was only with a previous patch, probably the third rewrite
-    // fixed it as a side-effect. In fact, the erase background style of drawing not 
-    // only works now, but is much better than paint-based updates (the paint event 
-    // handler flickers if the wxMediaCtrl shares a sizer with another child window, 
+    // fixed it as a side-effect. In fact, the erase background style of drawing not
+    // only works now, but is much better than paint-based updates (the paint event
+    // handler flickers if the wxMediaCtrl shares a sizer with another child window,
     // or is on a notebook)
     //  - Greg Hazel
-    m_ctrl->Connect(m_ctrl->GetId(), wxEVT_ERASE_BACKGROUND, 
+    ctrl->Connect(ctrl->GetId(), wxEVT_ERASE_BACKGROUND,
         wxEraseEventHandler(wxAMMediaEvtHandler::OnEraseBackground),
         NULL, (wxEvtHandler*) this);
-    //m_ctrl->Connect(m_ctrl->GetId(), wxEVT_PAINT, 
-    //    wxPaintEventHandler(wxAMMediaEvtHandler::OnPaint),
-    //    NULL, (wxEvtHandler*) this);
-
-    //
-    // As noted below, we need to catch the Top Level Window's
-    // move events because they are not sent to us if the media control
-    // size remains the same but it actually moves in window coordinates
-    //
-    wxWindow* pTheTLW = m_ctrl->GetParent();
-    while( pTheTLW->GetParent() )
-        pTheTLW = pTheTLW->GetParent();
 
-    //
-    //  FIXMEHACKFIXMEHACKFIXME
-    //  This is really nasty... basically the deal is not only above
-    //  but the repainting is messed up when the parent is maximized
-    //  too, so we've got to catch all 4 events!
-    //
-    m_ctrl->Connect(m_ctrl->GetId(), wxEVT_MOVE, 
-        wxMoveEventHandler(wxAMMediaEvtHandler::OnMove),
-        NULL, (wxEvtHandler*) this);
-    m_ctrl->Connect(m_ctrl->GetId(), wxEVT_SIZE, 
-        wxSizeEventHandler(wxAMMediaEvtHandler::OnSize),
-        NULL, (wxEvtHandler*) this);
-    pTheTLW->Connect(pTheTLW->GetId(), wxEVT_MOVE, 
-        wxMoveEventHandler(wxAMMediaEvtHandler::OnMove),
-        NULL, (wxEvtHandler*) this);
-    pTheTLW->Connect(pTheTLW->GetId(), wxEVT_SIZE, 
-        wxSizeEventHandler(wxAMMediaEvtHandler::OnSize),
-        NULL, (wxEvtHandler*) this);
     //
     // done...
     //
+    m_ctrl = ctrl;
     return true;
 }
 
@@ -1131,19 +1107,23 @@ bool wxAMMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
 // Adds a Video Mixing Renderer to a Filter Graph and obtains the
 // windowless control from it
 //---------------------------------------------------------------------------
-bool wxAMMediaBackend::SetWindowlessMode(IGraphBuilder* pGB, 
+bool wxAMMediaBackend::SetWindowlessMode(IGraphBuilder* pGB,
                                          IVMRWindowlessControl** ppVMC)
 {
+    HRESULT hr;
+
     //
     // Create and add a custom Video Mixing Render to the graph
     //
     IBaseFilter* pVMR;
-    if( CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC_SERVER,
-                     IID_IBaseFilter, (void**)&pVMR) != 0 )
+    if( ::CoCreateInstance(CLSID_VideoMixingRenderer, NULL,
+                CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVMR) != 0 )
         return false;
 
-    if ( pGB->AddFilter(pVMR, L"Video Mixing Renderer") != 0) 
+    hr = pGB->AddFilter(pVMR, L"Video Mixing Renderer");
+    if ( hr != 0)
     {
+        wxAMLOG(hr);
         pVMR->Release();
         return false;
     }
@@ -1151,29 +1131,35 @@ bool wxAMMediaBackend::SetWindowlessMode(IGraphBuilder* pGB,
     //
     // Set the graph to windowless mode
     //
-    IVMRFilterConfig* pConfig; 
-    if( pVMR->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig) != 0 ) 
+    IVMRFilterConfig* pConfig;
+    hr = pVMR->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig);
+    if( hr != 0 )
     {
+        wxAMLOG(hr);
         pVMR->Release();
         return false;
     }
 
-    if( pConfig->SetRenderingMode(2) != 0) //2 == VMRMode_Windowless
+    hr = pConfig->SetRenderingMode(2);
+    if( hr != 0) //2 == VMRMode_Windowless
     {
-        pConfig->Release(); 
+        wxAMLOG(hr);
+        pConfig->Release();
         pVMR->Release();
         return false;
     }
 
-    pConfig->Release(); 
+    pConfig->Release();
 
     //
     // Obtain the windowless control
     //
     IVMRWindowlessControl* pVMC;
-    if( pVMR->QueryInterface(IID_IVMRWindowlessControl, (void**)&pVMC) != 0 )
+    hr = pVMR->QueryInterface(IID_IVMRWindowlessControl, (void**)&pVMC);
+    if( hr != 0 )
     {
-        pVMR->Release(); 
+        wxAMLOG(hr);
+        pVMR->Release();
         return false;
     }
 
@@ -1185,8 +1171,8 @@ bool wxAMMediaBackend::SetWindowlessMode(IGraphBuilder* pGB,
     else
         pVMC->Release();
 
-    pVMR->Release(); 
-    return true; 
+    pVMR->Release();
+    return true;
 }
 
 //---------------------------------------------------------------------------
@@ -1203,41 +1189,80 @@ bool wxAMMediaBackend::SetWindowlessMode(IGraphBuilder* pGB,
 //---------------------------------------------------------------------------
 bool wxAMMediaBackend::Load(const wxString& fileName)
 {
+    HRESULT hr;
+
     //if previously loaded cleanup
     if(m_pVMC)
         Cleanup();
 
     //Create interfaces - we already checked for success in CreateControl
-    CoCreateInstance(CLSID_FilgraphManager, NULL, CLSCTX_INPROC_SERVER,
+    ::CoCreateInstance(CLSID_FilgraphManager, NULL, CLSCTX_INPROC_SERVER,
                      IID_IGraphBuilder, (void**)&m_pGB);
 
 
     // Set and clip output
     SetWindowlessMode(m_pGB, &m_pVMC);
-    if( m_pVMC->SetVideoClippingWindow((HWND)m_ctrl->GetHandle()) != 0 )
+    hr = m_pVMC->SetVideoClippingWindow((HWND)m_ctrl->GetHandle());
+
+    if(hr != 0)
     {
         m_bestSize.x = m_bestSize.y = 0;
-        wxASSERT(false);
+        wxAMFAIL(hr);
+        return false;
     }
 
     //load the graph & render
     if( m_pGB->RenderFile(fileName.wc_str(wxConvLocal), NULL) != 0 )
         return false;
 
+    //
     //Get the interfaces, all of them
-    wxAMVERIFY( m_pGB->QueryInterface(IID_IMediaEvent, (void**)&m_pME) );
-    wxAMVERIFY( m_pGB->QueryInterface(IID_IMediaControl, (void**)&m_pMC) );
-    wxAMVERIFY( m_pGB->QueryInterface(IID_IMediaPosition, (void**)&m_pMS) );
-    wxAMVERIFY( m_pGB->QueryInterface(IID_IBasicAudio, (void**)&m_pBA) );
+    //
+    hr = m_pGB->QueryInterface(IID_IMediaEvent, (void**)&m_pME);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return false;
+    }
+
+    hr = m_pGB->QueryInterface(IID_IMediaControl, (void**)&m_pMC);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return false;
+    }
+
+    hr = m_pGB->QueryInterface(IID_IMediaPosition, (void**)&m_pMS);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return false;
+    }
+
+    hr = m_pGB->QueryInterface(IID_IBasicAudio, (void**)&m_pBA);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        //not critical
+    }
 
+    //
     // Get original video size
-    if( m_pVMC->GetNativeVideoSize((LONG*)&m_bestSize.x, (LONG*)&m_bestSize.y, 
-                                   NULL, NULL) != 0 )
+    //
+    hr = m_pVMC->GetNativeVideoSize((LONG*)&m_bestSize.x, (LONG*)&m_bestSize.y,
+                                   NULL, NULL);
+    if(hr != 0)
     {
         m_bestSize.x = m_bestSize.y = 0;
-        wxASSERT(false);
+        wxAMFAIL(hr);
+        return false;
     }
 
+    if(m_bestSize.x == 0 && m_bestSize.y == 0)
+        m_bVideo = false;
+    else
+        m_bVideo = true;
+
     //
     // Force the parent window of this control to recalculate
     // the size of this if sizers are being used
@@ -1249,11 +1274,17 @@ bool wxAMMediaBackend::Load(const wxString& fileName)
     m_ctrl->GetParent()->Update();
     m_ctrl->SetSize(m_ctrl->GetSize());
 
+    //
+    //  Create the event thread
+    //
     m_pThread = new wxAMMediaThread;
     m_pThread->pThis = this;
     m_pThread->Create();
     m_pThread->Run();
 
+    //
+    //  done
+    //
     return true;
 }
 
@@ -1269,6 +1300,33 @@ bool wxAMMediaBackend::Load(const wxURI& location)
     return Load(location.BuildUnescapedURI());
 }
 
+//---------------------------------------------------------------------------
+// wxAMMediaBackend::Cleanup
+//
+// Releases all the directshow interfaces we use
+// TODO: Maybe only create one instance of IAMMultiMediaStream and reuse it
+// rather than recreating it each time?
+//---------------------------------------------------------------------------
+void wxAMMediaBackend::Cleanup()
+{
+    // RN:  This could be a bad ptr if load failed after
+    // m_pVMC was created
+    if(m_pThread)
+    {
+        m_pThread->Delete();
+        m_pThread = NULL;
+    }
+
+    // Release and zero DirectShow interfaces
+    SAFE_RELEASE(m_pMC);
+    SAFE_RELEASE(m_pME);
+    SAFE_RELEASE(m_pMS);
+    SAFE_RELEASE(m_pBA);
+    SAFE_RELEASE(m_pGB);
+    SAFE_RELEASE(m_pVMC);
+}
+
+
 //---------------------------------------------------------------------------
 // wxAMMediaBackend::Play
 //
@@ -1343,9 +1401,16 @@ bool wxAMMediaBackend::Stop()
 //---------------------------------------------------------------------------
 bool wxAMMediaBackend::SetPosition(wxLongLong where)
 {
-    return SUCCEEDED( m_pMS->put_CurrentPosition(
+    HRESULT hr = m_pMS->put_CurrentPosition(
                         ((LONGLONG)where.GetValue()) / 1000.0
-                                     ) );
+                                     );
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return false;
+    }
+
+    return true;
 }
 
 //---------------------------------------------------------------------------
@@ -1357,7 +1422,12 @@ bool wxAMMediaBackend::SetPosition(wxLongLong where)
 wxLongLong wxAMMediaBackend::GetPosition()
 {
     double outCur;
-    wxAMVERIFY( m_pMS->get_CurrentPosition(&outCur) );
+    HRESULT hr = m_pMS->get_CurrentPosition(&outCur);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return 0;
+    }
 
     //h,m,s,milli - outdur is in 1 second (double)
     outCur *= 1000;
@@ -1368,30 +1438,53 @@ wxLongLong wxAMMediaBackend::GetPosition()
 }
 
 //---------------------------------------------------------------------------
-// wxAMMediaBackend::SetVolume
+// wxAMMediaBackend::GetVolume
 //
-// Sets the volume through the IBasicAudio interface -
+// Gets the volume through the IBasicAudio interface -
 // value ranges from 0 (MAX volume) to -10000 (minimum volume).
 // -100 per decibel.
 //---------------------------------------------------------------------------
-bool wxAMMediaBackend::SetVolume(double dVolume)
+double wxAMMediaBackend::GetVolume()
 {
-    return SUCCEEDED(m_pBA->put_Volume( (long) ((dVolume-1.0) * 10000.0) ) );
+    if(m_pBA)
+    {
+        long lVolume;
+        HRESULT hr = m_pBA->get_Volume(&lVolume);
+        if(FAILED(hr))
+        {
+            wxAMLOG(hr);
+            return 0.0;
+        }
+
+        return (((double)(lVolume + 10000)) / 10000.0);
+    }
+
+    wxLogDebug(wxT("No directshow audio interface"));
+    return 0.0;
 }
 
 //---------------------------------------------------------------------------
-// wxAMMediaBackend::GetVolume
+// wxAMMediaBackend::SetVolume
 //
-// Gets the volume through the IBasicAudio interface -
+// Sets the volume through the IBasicAudio interface -
 // value ranges from 0 (MAX volume) to -10000 (minimum volume).
 // -100 per decibel.
 //---------------------------------------------------------------------------
-double wxAMMediaBackend::GetVolume()
+bool wxAMMediaBackend::SetVolume(double dVolume)
 {
-    long lVolume;
-    if ( SUCCEEDED( m_pBA->get_Volume(&lVolume) ) )
-        return (((double)(lVolume + 10000)) / 10000.0);
-    return 0.0;
+    if(m_pBA)
+    {
+        HRESULT hr = m_pBA->put_Volume( (long) ((dVolume-1.0) * 10000.0) );
+        if(FAILED(hr))
+        {
+            wxAMLOG(hr);
+            return false;
+        }
+        return true;
+    }
+
+    wxLogDebug(wxT("No directshow audio interface"));
+    return false;
 }
 
 //---------------------------------------------------------------------------
@@ -1400,14 +1493,19 @@ double wxAMMediaBackend::GetVolume()
 // 1) Obtains the duration of the media from IAMMultiMediaStream
 // 2) Converts that value to our time base, and returns it
 //
-// NB: With VBR MP3 files the default DirectShow MP3 render does not 
+// 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;
-    wxAMVERIFY( m_pMS->get_Duration(&outDuration) );
+    HRESULT hr = m_pMS->get_Duration(&outDuration);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return 0;
+    }
 
     //h,m,s,milli - outdur is in 1 second (double)
     outDuration *= 1000;
@@ -1436,7 +1534,12 @@ wxMediaState wxAMMediaBackend::GetState()
 double wxAMMediaBackend::GetPlaybackRate()
 {
     double dRate;
-    wxAMVERIFY( m_pMS->get_Rate(&dRate) );
+    HRESULT hr = m_pMS->get_Rate(&dRate);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return 0.0;
+    }
     return dRate;
 }
 
@@ -1448,31 +1551,16 @@ double wxAMMediaBackend::GetPlaybackRate()
 //---------------------------------------------------------------------------
 bool wxAMMediaBackend::SetPlaybackRate(double dRate)
 {
-    return m_pMS->put_Rate(dRate) == 0;
-}
-
-//---------------------------------------------------------------------------
-// wxAMMediaBackend::Cleanup
-//
-// Releases all the directshow interfaces we use
-// TODO: Maybe only create one instance of IAMMultiMediaStream and reuse it
-// rather than recreating it each time?
-//---------------------------------------------------------------------------
-void wxAMMediaBackend::Cleanup()
-{
-    m_pThread->Delete();
-    m_pThread = NULL;
+    HRESULT hr = m_pMS->put_Rate(dRate);
+    if(FAILED(hr))
+    {
+        wxAMLOG(hr);
+        return false;
+    }
 
-    // Release and zero DirectShow interfaces
-    SAFE_RELEASE(m_pMC);
-    SAFE_RELEASE(m_pME);
-    SAFE_RELEASE(m_pMS);
-    SAFE_RELEASE(m_pBA);
-    SAFE_RELEASE(m_pGB);
-    SAFE_RELEASE(m_pVMC);
+    return true;
 }
 
-
 //---------------------------------------------------------------------------
 // wxAMMediaBackend::GetVideoSize
 //
@@ -1488,13 +1576,14 @@ wxSize wxAMMediaBackend::GetVideoSize() const
 //
 // We take care of this in our redrawing
 //---------------------------------------------------------------------------
-void wxAMMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y), 
+void wxAMMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
                             int w, int h)
 {
-    if(m_pVMC)
+    //don't use deferred positioning on windows
+    if(m_pVMC && m_bVideo)
     {
         RECT srcRect, destRect;
-        
+
         //portion of video to display in window
         srcRect.top = 0; srcRect.left = 0;
         srcRect.bottom = m_bestSize.y; srcRect.right = m_bestSize.x;
@@ -1514,50 +1603,14 @@ void wxAMMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y),
         destRect.bottom = h; destRect.right = w;
 
         //set the windowless control positions
-        if( m_pVMC->SetVideoPosition(&srcRect, &destRect) != 0 )
-        {
-            wxASSERT_MSG(false, wxT("Could not set video position!"));
-        }
-
-/*
-        //oddly enough, it doesn't redraw the frame after moving...
-        //TODO: Use wxClientDC?
-        HDC hdc = ::GetDC((HWND)m_ctrl->GetHandle());
-        if( m_pVMC->RepaintVideo((HWND)m_ctrl->GetHandle(), 
-                                                hdc)  != 0 )
+        HRESULT hr = m_pVMC->SetVideoPosition(&srcRect, &destRect);
+        if(FAILED(hr))
         {
-            wxASSERT(false);
+            wxAMLOG(hr);
         }
-        ::ReleaseDC((HWND)m_ctrl->GetHandle(), hdc);
-*/
     }
 }
 
-//---------------------------------------------------------------------------
-// wxAMMediaEvtHandler::OnMove
-//
-// Oddly enough Move isn't called on MSW when the parent moves
-// and the child (us) doesn't, so we have to do it twice I guess :(
-//---------------------------------------------------------------------------
-void wxAMMediaEvtHandler::OnMove(wxMoveEvent& evt)
-{
-    wxAMMediaBackend* pThis = (wxAMMediaBackend*) this;
-    pThis->Move(pThis->m_ctrl->GetPosition().x, 
-                pThis->m_ctrl->GetPosition().y,
-                pThis->m_ctrl->GetSize().x,
-                pThis->m_ctrl->GetSize().y );
-    evt.Skip();
-}
-void wxAMMediaEvtHandler::OnSize(wxSizeEvent& evt)
-{
-    wxAMMediaBackend* pThis = (wxAMMediaBackend*) this;
-    pThis->Move(pThis->m_ctrl->GetPosition().x, 
-                pThis->m_ctrl->GetPosition().y,
-                pThis->m_ctrl->GetSize().x,
-                pThis->m_ctrl->GetSize().y );
-    evt.Skip();
-}
-
 //---------------------------------------------------------------------------
 // wxAMMediaThread::Entry
 //
@@ -1580,13 +1633,17 @@ wxThread::ExitCode wxAMMediaThread::Entry()
                                       (LONG_PTR *) &evParam2, 0) == 0 )
         {
             // Cleanup memory that GetEvent allocated
-            if( pThis->m_pME->FreeEventParams(evCode, evParam1, evParam2) != 0 )
+            HRESULT hr = pThis->m_pME->FreeEventParams(evCode,
+                                                evParam1, evParam2);
+            if(hr != 0)
             {
-                wxASSERT(false);
+                //Even though this makes a messagebox this
+                //is windows where we can do gui stuff in seperate
+                //threads :)
+                wxFAIL_MSG(pThis->GetErrorString(hr));
             }
-
             // If this is the end of the clip, notify handler
-            if(1 == evCode) //EC_COMPLETE
+            else if(1 == evCode) //EC_COMPLETE
             {
                 pThis->OnStop();
             }
@@ -1632,14 +1689,15 @@ void wxAMMediaBackend::OnStop()
 void wxAMMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt)
 {
     wxAMMediaBackend* pThis = (wxAMMediaBackend*) this;
-    if(pThis->m_pVMC)
+    if(pThis->m_pVMC && pThis->m_bVideo)
     {
         //TODO: Use wxClientDC?
         HDC hdc = ::GetDC((HWND)pThis->m_ctrl->GetHandle());
-        if( pThis->m_pVMC->RepaintVideo((HWND)pThis->m_ctrl->GetHandle(), 
-                                        hdc)  != 0 )
+        HRESULT hr = pThis->m_pVMC->RepaintVideo((HWND)pThis->m_ctrl->GetHandle(),
+                                        hdc);
+        if(FAILED(hr))
         {
-            wxASSERT(false);
+            wxFAIL_MSG(pThis->GetErrorString(hr));
         }
         ::ReleaseDC((HWND)pThis->m_ctrl->GetHandle(), hdc);
     }
@@ -1649,25 +1707,6 @@ void wxAMMediaEvtHandler::OnEraseBackground(wxEraseEvent& evt)
     }
 }
 
-//---------------------------------------------------------------------------
-// wxAMMediaEvtHandler::OnPaint
-//
-// Handle redrawing
-//---------------------------------------------------------------------------
-void wxAMMediaEvtHandler::OnPaint(wxPaintEvent& WXUNUSED(evt))
-{
-    wxAMMediaBackend* pThis = (wxAMMediaBackend*) this;
-    wxPaintDC dc(pThis->m_ctrl);
-    if( pThis->m_pVMC )
-    {
-        if( pThis->m_pVMC->RepaintVideo((HWND)pThis->m_ctrl->GetHandle(), 
-                                                (HDC)dc.GetHDC())  != 0 )
-        {
-            wxASSERT(false);
-        }
-    }
-}
-
 //---------------------------------------------------------------------------
 // End of wxAMMediaBackend
 //---------------------------------------------------------------------------