]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/mediactrl.cpp
more wxPostEvent MT fixes
[wxWidgets.git] / src / msw / mediactrl.cpp
index 96c8361634ef4e49763b2bf7f3428d69549b0058..13369b2a61058c8b422ba7058f324e9ca6fc74a5 100644 (file)
@@ -2,7 +2,7 @@
 // Name:        msw/mediactrl.cpp
 // Purpose:     wxMediaCtrl MSW
 // Author:      Ryan Norton <wxprojects@comcast.net>
-// Modified by: 
+// Modified by:
 // Created:     11/07/04
 // RCS-ID:      $Id$
 // Copyright:   (c) Ryan Norton
@@ -33,8 +33,8 @@
 //###########################################################################
 
 IMPLEMENT_CLASS(wxMediaCtrl, wxControl);
-IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent); 
-DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED); 
+IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent);
+DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED);
 
 //---------------------------------------------------------------------------
 //  wxMediaCtrlImpl
@@ -46,10 +46,10 @@ public:
     wxMediaCtrlImpl() : m_bLoaded(false)
     {                                                                   }
 
-    virtual ~wxMediaCtrlImpl() 
+    virtual ~wxMediaCtrlImpl()
     {                               }
 
-    virtual bool Create(wxMediaCtrl* WXUNUSED(ctrl)) 
+    virtual bool Create(wxMediaCtrl* WXUNUSED(ctrl))
     {   return false;               }
 
     virtual bool Play() { return false; }
@@ -70,7 +70,7 @@ public:
 
     virtual double GetPlaybackRate() { return 0; }
     virtual bool SetPlaybackRate(double) { return false; }
-    
+
     virtual bool MSWWindowProc(WXUINT, WXWPARAM, WXLPARAM) { return false; }
 
     bool IsLoaded()
@@ -149,7 +149,6 @@ public:
 //---------------------------------------------------------------------------
 
 #include <mmsystem.h>
-#include <digitalv.h>
 
 class wxWMMEMediaCtrlImpl : public wxMediaCtrlImpl
 {
@@ -179,53 +178,13 @@ public:
     virtual double GetPlaybackRate();
     virtual bool SetPlaybackRate(double);
 
+    bool MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
+
     MCIDEVICEID m_hDev;
     wxMediaCtrl* m_ctrl;
     bool m_bVideo;
 };
 
-//---------------------------------------------------------------------------
-//  wxAVIFileMediaCtrlImpl
-//---------------------------------------------------------------------------
-/*
-#include <Vfw.h>
-//msvfw32.dll
-//#pragma comment(lib, "vfw32.lib")
-
-class wxAVIFileMediaCtrlImpl : public wxMediaCtrlImpl
-{
-public:
-
-    wxAVIFileMediaCtrlImpl();
-    ~wxAVIFileMediaCtrlImpl();
-
-    virtual bool Create(wxMediaCtrl* ctrl);
-
-    virtual bool Play();
-    virtual bool Pause();
-    virtual bool Stop();
-
-    virtual bool Load(const wxString& fileName);
-    virtual bool Load(const wxURI& location);
-
-    virtual wxMediaState GetState();
-
-    virtual bool SetPosition(long where);
-    virtual long GetPosition();
-    virtual long GetDuration();
-
-    virtual void DoMoveWindow(int x, int y, int w, int h);
-    wxSize DoGetBestSize() const;
-
-    virtual double GetPlaybackRate();
-    virtual bool SetPlaybackRate(double);
-
-    HMODULE m_hDll;
-    PAVIFILE m_hAVIFile;
-    wxMediaCtrl* m_ctrl;
-};
-*/
-
 //###########################################################################
 //
 //  IMPLEMENTATION
@@ -238,12 +197,12 @@ public:
 //
 //---------------------------------------------------------------------------
 
-bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxString& fileName, 
-                         const wxPoint& pos, const wxSize& size, 
+bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxString& fileName,
+                         const wxPoint& pos, const wxSize& size,
                          long style, long WXUNUSED(driver), const wxString& name)
 {
     //base create
-    if ( !wxControl::Create(parent, id, pos, size, (style | wxNO_BORDER) | wxCLIP_CHILDREN, 
+    if ( !wxControl::Create(parent, id, pos, size, (style | wxNO_BORDER) | wxCLIP_CHILDREN,
                             wxDefaultValidator, name) )
         return false;
 
@@ -276,12 +235,12 @@ bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxString& fileNa
     return true;
 }
 
-bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxURI& location, 
-                         const wxPoint& pos, const wxSize& size, 
+bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxURI& location,
+                         const wxPoint& pos, const wxSize& size,
                          long style, long WXUNUSED(driver), const wxString& name)
 {
     //base create
-    if ( !wxControl::Create(parent, id, pos, size, (style | wxNO_BORDER) | wxCLIP_CHILDREN, 
+    if ( !wxControl::Create(parent, id, pos, size, (style | wxNO_BORDER) | wxCLIP_CHILDREN,
                             wxDefaultValidator, name) )
         return false;
 
@@ -424,7 +383,7 @@ wxMediaCtrl::~wxMediaCtrl()
 //
 //---------------------------------------------------------------------------
 
-#if wxUSE_DIRECTSHOW 
+#if wxUSE_DIRECTSHOW
 
 wxDXMediaCtrlImpl::wxDXMediaCtrlImpl() : m_pGB(NULL)
 {
@@ -450,14 +409,14 @@ bool wxDXMediaCtrlImpl::Create(wxMediaCtrl* ctrl)
 bool wxDXMediaCtrlImpl::Load(const wxString& fileName)
 {
     if(m_bLoaded)
-        Cleanup();                        
-        
+        Cleanup();
+
     SAFE_RELEASE(m_pGB);
 
     CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
                       IID_IGraphBuilder, (void**)&m_pGB);
 
-    //load the graph & render 
+    //load the graph & render
     if( FAILED(m_pGB->RenderFile(fileName.wc_str(wxConvLocal), NULL)) )
         return false;
 
@@ -481,7 +440,7 @@ bool wxDXMediaCtrlImpl::Load(const wxString& fileName)
 
         nSX = nSY = 0;
     }
-    else 
+    else
     {
         m_bVideo = true;
     }
@@ -531,7 +490,13 @@ bool wxDXMediaCtrlImpl::Pause()
 
 bool wxDXMediaCtrlImpl::Stop()
 {
-    return SUCCEEDED( m_pMC->Stop() ) && SetPosition(0);
+    bool bOK = SUCCEEDED( m_pMC->Stop() );
+
+    //We don't care if it can't get to the beginning in directshow -
+    //it could be a non-seeking filter (wince midi) in which case playing
+    //starts all over again
+    SetPosition(0);
+    return bOK;
 }
 
 bool wxDXMediaCtrlImpl::SetPosition(long where)
@@ -540,9 +505,9 @@ bool wxDXMediaCtrlImpl::SetPosition(long where)
     LONGLONG pos = ((LONGLONG)where) * 10000;
 
     return SUCCEEDED( m_pMS->SetPositions(
-                                &pos, 
+                                &pos,
                                 AM_SEEKING_AbsolutePositioning,
-                                NULL, 
+                                NULL,
                                 AM_SEEKING_NoPositioning
                                     ) );
 }
@@ -571,7 +536,7 @@ wxMediaState wxDXMediaCtrlImpl::GetState()
     HRESULT hr;
     OAFilterState theState;
     hr = m_pMC->GetState(INFINITE, &theState);
-    
+
     wxASSERT( SUCCEEDED(hr) );
 
     //MSW state is the same as ours
@@ -603,8 +568,8 @@ bool wxDXMediaCtrlImpl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPa
 
         // Process all queued events
         while(SUCCEEDED(m_pME->GetEvent(&evCode, (LONG_PTR *) &evParam1,
-                                       (LONG_PTR *) &evParam2, 0) 
-                       ) 
+                                       (LONG_PTR *) &evParam2, 0)
+                       )
              )
         {
             // Free memory associated with callback, since we're not using it
@@ -613,15 +578,18 @@ bool wxDXMediaCtrlImpl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPa
             // If this is the end of the clip, notify handler
             if(EC_COMPLETE == evCode)
             {
+                //Interestingly enough, DirectShow does not actually stop
+                //the filters - even when it reaches the end!
 #ifdef __WXDEBUG__
                 wxASSERT( Stop() );
 #else
                 Stop();
 #endif
+
                 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED, m_ctrl->GetId());
                 m_ctrl->GetParent()->ProcessEvent(theEvent);
             }
-        }    
+        }
         return true;
     }
     return false;
@@ -674,9 +642,57 @@ void wxDXMediaCtrlImpl::DoMoveWindow(int x, int y, int w, int h)
 //
 //---------------------------------------------------------------------------
 
+//
+// Cruft to simulate digitalv.h
+//
+
+typedef struct {
+    DWORD_PTR   dwCallback;
+#ifdef MCI_USE_OFFEXT
+    POINT   ptOffset;
+    POINT   ptExtent;
+#else  
+    RECT    rc;
+#endif
+} MCI_DGV_RECT_PARMS;
+
+typedef struct {
+    DWORD_PTR   dwCallback;
+    HWND    hWnd;
+#ifndef _WIN32
+    WORD    wReserved1;
+#endif
+    UINT    nCmdShow;
+#ifndef _WIN32
+    WORD    wReserved2;
+#endif
+    LPSTR   lpstrText;
+} MCI_DGV_WINDOW_PARMSA;
+
+typedef struct {
+    DWORD_PTR   dwCallback;
+    HWND    hWnd;
+#ifndef _WIN32
+    WORD    wReserved1;
+#endif
+    UINT    nCmdShow;
+#ifndef _WIN32
+    WORD    wReserved2;
+#endif
+    LPWSTR  lpstrText;
+} MCI_DGV_WINDOW_PARMSW;
+#ifdef UNICODE
+typedef MCI_DGV_WINDOW_PARMSW MCI_DGV_WINDOW_PARMS;
+#else
+typedef MCI_DGV_WINDOW_PARMSA MCI_DGV_WINDOW_PARMS;
+#endif // UNICODE
+
 wxWMMEMediaCtrlImpl::wxWMMEMediaCtrlImpl() : m_bVideo(false)
 {
-
+/*        TCHAR sz[5000];
+        mciGetErrorString(nError, sz, 5000);
+            wxMessageBox(wxString::Format(_T("Error:%s"), sz));
+  */
 }
 
 wxWMMEMediaCtrlImpl::~wxWMMEMediaCtrlImpl()
@@ -685,29 +701,11 @@ wxWMMEMediaCtrlImpl::~wxWMMEMediaCtrlImpl()
 }
 
 bool wxWMMEMediaCtrlImpl::Create(wxMediaCtrl* ctrl)
-{    
+{
     m_ctrl = ctrl;
     return true;
 }
 
-bool wxWMMEMediaCtrlImpl::Play()
-{
-    return (mciSendCommand(m_hDev, MCI_PLAY, 0, 0) == 0) ||
-           (mciSendCommand(m_hDev, MCI_RESUME, 0, 0) == 0);
-}
-
-bool wxWMMEMediaCtrlImpl::Pause()
-{
-    return (mciSendCommand(m_hDev, MCI_PAUSE, MCI_WAIT, 0) == 0);
-}
-
-bool wxWMMEMediaCtrlImpl::Stop()
-{
-    return (mciSendCommand(m_hDev, MCI_STOP, MCI_WAIT, 0) == 0);
-}
-
-#include "wx/log.h"
-
 bool wxWMMEMediaCtrlImpl::Load(const wxString& fileName)
 {
     if(m_bLoaded)
@@ -716,32 +714,17 @@ bool wxWMMEMediaCtrlImpl::Load(const wxString& fileName)
     MCI_OPEN_PARMS openParms;
     MCI_SET_PARMS setParms;
 
-    memset(&openParms, 0, sizeof(MCI_DGV_OPEN_PARMS));
     openParms.lpstrElementName = (wxChar*) fileName.c_str();
 
-    bool bFound = false;
-
-    for(size_t i = MCI_DEVTYPE_FIRST; i <= MCI_DEVTYPE_LAST; ++i)
-    {
-        openParms.lpstrDeviceType = (LPSTR)i;
-
-        DWORD nError;
-
-        if ((nError = mciSendCommand(0, MCI_OPEN,
-                 MCI_OPEN_ELEMENT|MCI_OPEN_ELEMENT|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID,
-                (DWORD)(LPVOID)&openParms)) == 0)  
-        {
-            bFound = true;
-            break;
-        }
-    }
-
-    if(!bFound)
-        return false;
+    //Here's where the trick lies - if you don't specify MCI_OPEN_TYPE,
+    //then it actually automagically finds the device for you!
+    if ( mciSendCommand(0, MCI_OPEN,
+         MCI_OPEN_ELEMENT,
+        (DWORD)(LPVOID)&openParms) != 0)
+    return false;
 
     m_hDev = openParms.wDeviceID;
 
-
     setParms.dwCallback = 0;
     setParms.dwTimeFormat = MCI_FORMAT_MILLISECONDS;
 
@@ -749,17 +732,21 @@ bool wxWMMEMediaCtrlImpl::Load(const wxString& fileName)
                          (DWORD)(LPVOID)&setParms) != 0)
         return false;
 
-
-    //TODO: Does this work?
-    /*
     MCI_DGV_WINDOW_PARMS windowParms;
 
-  windowParms.hWnd = (HWND)m_ctrl->GetHWND();
+    windowParms.hWnd = (HWND)m_ctrl->GetHandle();
     m_bVideo = (mciSendCommand(m_hDev, MCI_WINDOW,
-                        MCI_DGV_WINDOW_HWND, (DWORD)(LPVOID)&windowParms) == 0);
-*/
+                         0x00010000L //MCI_DGV_WINDOW_HWND
+                         ,
+                         (DWORD)(LPVOID)&windowParms) == 0);
     m_bLoaded = true;
 
+    //work around refresh issues
+    m_ctrl->InvalidateBestSize();
+    m_ctrl->GetParent()->Layout();
+    m_ctrl->GetParent()->Refresh();
+    m_ctrl->GetParent()->Update();
+
     return true;
 }
 
@@ -768,6 +755,28 @@ bool wxWMMEMediaCtrlImpl::Load(const wxURI& WXUNUSED(location))
     return false;
 }
 
+bool wxWMMEMediaCtrlImpl::Play()
+{
+    //the directshow driver ("mpegvideo") will crash if we don't do a playParms here
+    MCI_PLAY_PARMS playParms;
+    playParms.dwCallback = (DWORD)(HWND)m_ctrl->GetHWND();
+    bool bOK = mciSendCommand(m_hDev, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPVOID)&playParms) == 0;
+    return (bOK) ;/*||
+           (mciSendCommand(m_hDev, MCI_RESUME, 0, 0) == 0);*/
+}
+
+bool wxWMMEMediaCtrlImpl::Pause()
+{
+    return (mciSendCommand(m_hDev, MCI_PAUSE, MCI_WAIT, 0) == 0);
+}
+
+bool wxWMMEMediaCtrlImpl::Stop()
+{
+    return (mciSendCommand(m_hDev, MCI_STOP, MCI_WAIT, 0) == 0) &&
+           (mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0) == 0);
+}
+
+
 wxMediaState wxWMMEMediaCtrlImpl::GetState()
 {
     MCI_STATUS_PARMS statusParms;
@@ -793,10 +802,6 @@ bool wxWMMEMediaCtrlImpl::SetPosition(long where)
 
     if( mciSendCommand(m_hDev, MCI_SEEK, MCI_TO, (DWORD)(LPVOID)&seekParms) != 0)
         return false;
-/*        TCHAR sz[5000];
-        mciGetErrorString(nError, sz, 5000);
-            wxMessageBox(wxString::Format(_T("Error:%s"), sz));
-  */          
 
     if (bReplay)
         return Play();
@@ -807,9 +812,9 @@ bool wxWMMEMediaCtrlImpl::SetPosition(long where)
 long wxWMMEMediaCtrlImpl::GetPosition()
 {
     MCI_STATUS_PARMS statusParms;
-    
-    statusParms.dwItem = MCI_STATUS_POSITION; 
-    if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM, 
+
+    statusParms.dwItem = MCI_STATUS_POSITION;
+    if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
         (DWORD)(LPSTR)&statusParms) != 0)
         return 0;
 
@@ -819,9 +824,9 @@ long wxWMMEMediaCtrlImpl::GetPosition()
 long wxWMMEMediaCtrlImpl::GetDuration()
 {
     MCI_STATUS_PARMS statusParms;
-    
-    statusParms.dwItem = MCI_STATUS_LENGTH; 
-    if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM, 
+
+    statusParms.dwItem = MCI_STATUS_LENGTH;
+    if (mciSendCommand(m_hDev, MCI_STATUS, MCI_STATUS_ITEM,
         (DWORD)(LPSTR)&statusParms) != 0)
         return 0;
 
@@ -836,13 +841,12 @@ wxSize wxWMMEMediaCtrlImpl::DoGetBestSize() const
 {
     if(m_bVideo)
     {
-        //TODO:  Does this work?
-        /*
-        MCI_DGV_RECT_PARMS rect; 
+        MCI_DGV_RECT_PARMS rect;
 
-        mciSendCommand(m_hDev, MCI_WHERE, MCI_DGV_WHERE_SOURCE, (DWORD)(LPSTR)&rect);
+        mciSendCommand(m_hDev, MCI_WHERE, 0x00020000L//MCI_DGV_WHERE_SOURCE
+            ,
+            (DWORD)(LPSTR)&rect);
         return wxSize(rect.rc.right, rect.rc.bottom);
-        */
     }
     return wxSize(0,0);
 }
@@ -857,126 +861,26 @@ bool wxWMMEMediaCtrlImpl::SetPlaybackRate(double)
     return false;
 }
 
-//---------------------------------------------------------------------------
-//
-//  wxAVIFileMediaCtrlImpl
-//
-//---------------------------------------------------------------------------
-
-//---------------------------------------------------------------------------
-//  Functions located in msvfw32.dll
-//---------------------------------------------------------------------------
-
-/*
-
-typedef void (WINAPI *LPAVIFileInit) ();
-typedef void (WINAPI *LPAVIFileExit) ();
-
-typedef ULONG (WINAPI *LPAVIFileOpen) (
-PAVIFILE FAR * ppfile, 
-const wxChar* szFile,
-UINT uMode, 
-LPCLSID lpHandler
-);
-
-typedef ULONG (WINAPI *LPAVIFileRelease) (PAVIFILE pfile);
-
-wxAVIFileMediaCtrlImpl::wxAVIFileMediaCtrlImpl() 
-{
-}
-
-wxAVIFileMediaCtrlImpl::~wxAVIFileMediaCtrlImpl()
-{
-}
-
-bool wxAVIFileMediaCtrlImpl::Create(wxMediaCtrl* ctrl)
-{    
-    m_hDll = ::LoadLibrary(_T("avifil32.dll"));
-    
-    if(m_hDll == NULL)
-        return false;
-
-    LPAVIFileInit pAVIFileInit = (LPAVIFileInit) ::GetProcAddress(m_hDll, _T("AVIFileInit"));
-
-    if(!pAVIFileInit)
-        return false;
-
-    (*pAVIFileInit)();
-
-    m_ctrl = ctrl;
-    return false;
-}
-
-
-bool wxAVIFileMediaCtrlImpl::Load(const wxString& fileName)
-{
-//    if( AVIFileOpen(&m_hAVIFile, fileName.c_str(), OF_SHARE_DENY_WRITE, 0L) != 0)
-        return false;
-
-    m_bLoaded = true;
-
-    return true;
-}
-
-bool wxAVIFileMediaCtrlImpl::Load(const wxURI& WXUNUSED(location))
+bool wxWMMEMediaCtrlImpl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 {
-    return false;
-}
-
-bool wxAVIFileMediaCtrlImpl::Play()
-{
-    return 0;
-}
-
-bool wxAVIFileMediaCtrlImpl::Pause()
-{
-    return 0;
-}
-
-bool wxAVIFileMediaCtrlImpl::Stop()
-{
-    return 0;
-}
-
-wxMediaState wxAVIFileMediaCtrlImpl::GetState()
-{
-    return wxMEDIASTATE_STOPPED;
-}
-
-bool wxAVIFileMediaCtrlImpl::SetPosition(long where)
-{
-    return 0;
-}
-
-long wxAVIFileMediaCtrlImpl::GetPosition()
-{
-    return 0;
-}
-
-long wxAVIFileMediaCtrlImpl::GetDuration()
-{
-    return 0;
-}
-
-void wxAVIFileMediaCtrlImpl::DoMoveWindow(int, int, int, int)
-{
-}
-
-wxSize wxAVIFileMediaCtrlImpl::DoGetBestSize() const
-{
-    return wxSize(0,0);
-}
-
-double wxAVIFileMediaCtrlImpl::GetPlaybackRate()
-{
-    return 1.0;
-}
+    if(nMsg == MM_MCINOTIFY)
+    {
+        wxASSERT(lParam == (WXLPARAM) m_hDev);
+        if(wParam == (WXWPARAM) MCI_NOTIFY_SUCCESSFUL && lParam == (WXLPARAM) m_hDev)
+        {
+#ifdef __WXDEBUG__
+            wxASSERT(mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0) == 0);
+#else
+            mciSendCommand(m_hDev, MCI_SEEK, MCI_SEEK_TO_START, 0);
+#endif
 
-bool wxAVIFileMediaCtrlImpl::SetPlaybackRate(double)
-{
+            wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED, m_ctrl->GetId());
+            m_ctrl->GetParent()->ProcessEvent(theEvent);
+        }
+        return true;
+    }
     return false;
 }
 
-  */
+#endif //wxUSE_MEDIACTRL
 
-#endif //wxUSE_MEDIACTRL
\ No newline at end of file