]> git.saurik.com Git - wxWidgets.git/commitdiff
base wxMediaCtrl files
authorRyan Norton <wxprojects@comcast.net>
Thu, 11 Nov 2004 05:21:02 +0000 (05:21 +0000)
committerRyan Norton <wxprojects@comcast.net>
Thu, 11 Nov 2004 05:21:02 +0000 (05:21 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30443 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/mac/carbon/mediactrl.h [new file with mode: 0644]
include/wx/mediactrl.h [new file with mode: 0644]
include/wx/msw/mediactrl.h [new file with mode: 0644]
src/mac/carbon/mediactrl.cpp [new file with mode: 0644]
src/msw/mediactrl.cpp [new file with mode: 0644]

diff --git a/include/wx/mac/carbon/mediactrl.h b/include/wx/mac/carbon/mediactrl.h
new file mode 100644 (file)
index 0000000..b2a5681
--- /dev/null
@@ -0,0 +1,120 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/msw/moviectrl.h
+// Purpose:     wxMediaCtrl mac
+// Author:      Ryan Norton <wxprojects@comcast.net>
+// Modified by: 
+// Created:     11/07/04
+// RCS-ID:      $Id$
+// Copyright:   (c) Ryan Norton
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/defs.h"
+
+#if wxUSE_MEDIACTRL
+
+#include "wx/control.h"
+#include "wx/uri.h"
+
+#ifdef __WXMSW__
+    typedef struct MovieRecord* WXMOVIE;
+#else
+    typedef struct MovieType**  WXMOVIE;
+#endif
+    
+enum wxMediaState
+{
+    wxMEDIASTATE_STOPPED,
+    wxMEDIASTATE_PAUSED,
+    wxMEDIASTATE_PLAYING
+};
+
+
+class wxMediaCtrl : public wxControl
+{
+public:
+    wxMediaCtrl() : m_bLoaded(false)
+    {                                                                   }
+
+    wxMediaCtrl(wxWindow* parent, wxWindowID id, const wxString& fileName,
+                const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, 
+                long style = 0, long driver = 0, const wxString& name = wxPanelNameStr) : m_bLoaded(false)
+    {   Create(parent, id, fileName, pos, size, style, driver, name);    } 
+
+
+    wxMediaCtrl(wxWindow* parent, wxWindowID id, const wxURI& location,
+                const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, 
+                long style = 0, long driver = 0, const wxString& name = wxPanelNameStr) : m_bLoaded(false)
+    {   Create(parent, id, location, pos, size, style, driver, name);    } 
+
+    ~wxMediaCtrl();
+
+    bool Create(wxWindow* parent, wxWindowID id, const wxString& fileName,
+                const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, 
+                long style = 0, long driver = 0, const wxString& name = wxPanelNameStr);
+
+    bool Create(wxWindow* parent, wxWindowID id, const wxURI& location,
+                const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, 
+                long style = 0, long driver = 0, const wxString& name = wxPanelNameStr);
+
+    bool Play();
+    bool Pause();
+    bool Stop();
+
+    bool Load(const wxString& fileName);
+    bool Load(const wxURI& location);
+    
+    wxMediaState GetState();
+
+    double GetPlaybackRate();
+    bool SetPlaybackRate(double dRate);
+
+    bool SetPosition(long where);
+    long GetPosition();
+    long GetDuration();
+
+protected:
+    virtual void DoMoveWindow(int x, int y, int w, int h);
+    bool DoCreate(wxWindow* parent, wxWindowID id, 
+                         const wxPoint& pos, const wxSize& size, 
+                         long style, const wxString& name);
+
+    wxSize DoGetBestSize() const;
+    bool InitQT();
+    void Cleanup();
+    void FinishLoad();
+
+    bool m_bLoaded;
+
+    WXMOVIE m_movie;
+    wxSize m_bestSize;
+    class _wxQTTimer* m_timer;
+
+    friend class _wxQTTimer;
+    
+    DECLARE_DYNAMIC_CLASS(wxMediaCtrl);
+};
+
+//Event stuff
+class WXDLLEXPORT wxMediaEvent : public wxNotifyEvent 
+{ 
+public:
+    wxMediaEvent(wxEventType commandType = wxEVT_NULL, int id = 0) 
+        : wxNotifyEvent(commandType, id) 
+    {               }
+    
+    wxMediaEvent(const wxMediaEvent &clone) 
+            : wxNotifyEvent(clone.GetEventType(), clone.GetId()) 
+    {               }
+
+    wxEvent *Clone() { return new wxMediaEvent(*this); } 
+   
+    DECLARE_DYNAMIC_CLASS(wxMediaEvent) 
+}; 
+
+#define wxMEDIA_FINISHED_ID    13000 
+DECLARE_EVENT_TYPE(wxEVT_MEDIA_FINISHED, wxMEDIA_FINISHED_ID) 
+typedef void (wxEvtHandler::*wxMediaEventFunction)(wxMediaEvent&); 
+#define EVT_MEDIA_FINISHED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_FINISHED, winid, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxMediaEventFunction) & fn, (wxObject *) NULL ), 
+
+#endif // wxUSE_MOVIECTRL
\ No newline at end of file
diff --git a/include/wx/mediactrl.h b/include/wx/mediactrl.h
new file mode 100644 (file)
index 0000000..8836ab9
--- /dev/null
@@ -0,0 +1,18 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/mediactrl.h
+// Purpose:     wxMediaCtrl class
+// Author:      Ryan Norton <wxprojects@comcast.net>
+// Modified by: 
+// Created:     11/07/04
+// RCS-ID:      $Id$
+// Copyright:   (c) Ryan Norton
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#if defined(__WXMSW__)
+#include "wx/msw/mediactrl.h"
+#elif defined(__WXMAC__)
+#include "wx/mac/mediactrl.h"
+#else
+#error wxMediaCtrl not supported on this platform!
+#endif
\ No newline at end of file
diff --git a/include/wx/msw/mediactrl.h b/include/wx/msw/mediactrl.h
new file mode 100644 (file)
index 0000000..9c59d05
--- /dev/null
@@ -0,0 +1,104 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        wx/msw/mediactrl.h
+// Purpose:     DirectX7+ wxMediaCtrl MSW 
+// Author:      Ryan Norton <wxprojects@comcast.net>
+// Modified by: 
+// Created:     11/07/04
+// RCS-ID:      $Id$
+// Copyright:   (c) Ryan Norton
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+#include "wx/defs.h"
+
+#if wxUSE_MEDIACTRL
+
+#include "wx/control.h"
+#include "wx/uri.h"
+
+enum wxMediaState
+{
+    wxMEDIASTATE_STOPPED,
+    wxMEDIASTATE_PAUSED,
+    wxMEDIASTATE_PLAYING
+};
+
+class wxMediaCtrl : public wxControl
+{
+public:
+    wxMediaCtrl() : m_imp(NULL)
+    {                                                                   }
+
+    wxMediaCtrl(wxWindow* parent, wxWindowID id, const wxString& fileName, 
+                const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, 
+                long style = 0, long driver = 0, const wxString& name = wxPanelNameStr) : m_imp(NULL)
+    {   Create(parent, id, fileName, pos, size, style, driver, name);    } 
+
+
+    wxMediaCtrl(wxWindow* parent, wxWindowID id, const wxURI& location,
+                const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, 
+                long style = 0, long driver = 0, const wxString& name = wxPanelNameStr) : m_imp(NULL)
+    {   Create(parent, id, location, pos, size, style, driver, name);    } 
+
+    ~wxMediaCtrl();
+
+    bool Create(wxWindow* parent, wxWindowID id, const wxString& fileName, 
+                const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, 
+                long style = 0, long driver = 0, const wxString& name = wxPanelNameStr);
+
+    bool Create(wxWindow* parent, wxWindowID id, const wxURI& location, 
+                const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, 
+                long style = 0, long driver = 0, const wxString& name = wxPanelNameStr);
+
+    bool Play();
+    bool Pause();
+    bool Stop();
+
+    bool Load(const wxString& fileName);
+    bool Load(const wxURI& location);
+
+    wxMediaState GetState();
+
+    double GetPlaybackRate();
+    bool SetPlaybackRate(double dRate);
+
+    bool SetPosition(long where);
+    long GetPosition();
+    long GetDuration();
+
+protected:
+    virtual void DoMoveWindow(int x, int y, int w, int h);
+    wxSize DoGetBestSize() const;
+
+    //msw-specific - we need to overload the window proc
+    WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
+
+    class wxMediaCtrlImpl* m_imp;
+    bool m_bLoaded;
+    
+    DECLARE_DYNAMIC_CLASS(wxMediaCtrl);
+};
+
+//Event stuff
+class WXDLLEXPORT wxMediaEvent : public wxNotifyEvent 
+{ 
+public:
+    wxMediaEvent(wxEventType commandType = wxEVT_NULL, int id = 0) 
+        : wxNotifyEvent(commandType, id) 
+    {               }
+    
+    wxMediaEvent(const wxMediaEvent &clone) 
+            : wxNotifyEvent(clone.GetEventType(), clone.GetId()) 
+    {               }
+
+    wxEvent *Clone() { return new wxMediaEvent(*this); } 
+   
+    DECLARE_DYNAMIC_CLASS(wxMediaEvent) 
+}; 
+
+#define wxMEDIA_FINISHED_ID    13000 
+DECLARE_EVENT_TYPE(wxEVT_MEDIA_FINISHED, wxMEDIA_FINISHED_ID) 
+typedef void (wxEvtHandler::*wxMediaEventFunction)(wxMediaEvent&); 
+#define EVT_MEDIA_FINISHED(winid, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_MEDIA_FINISHED, winid, wxID_ANY, (wxObjectEventFunction) (wxEventFunction) (wxMediaEventFunction) & fn, (wxObject *) NULL ), 
+
+#endif // wxUSE_MEDIACTRL
\ No newline at end of file
diff --git a/src/mac/carbon/mediactrl.cpp b/src/mac/carbon/mediactrl.cpp
new file mode 100644 (file)
index 0000000..8d7644e
--- /dev/null
@@ -0,0 +1,446 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        mac/carbon/moviectrl.cpp
+// Purpose:     wxMediaCtrl MAC CARBON QT
+// Author:      Ryan Norton <wxprojects@comcast.net>
+// Modified by: 
+// Created:     11/07/04
+// RCS-ID:      $Id$
+// Copyright:   (c) Ryan Norton
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+//#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
+//#pragma implementation "moviectrl.h"
+//#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include "wx/mac/carbon/mediactrl.h"
+
+#if wxUSE_MEDIACTRL
+
+#include "wx/timer.h"
+
+IMPLEMENT_CLASS(wxMediaCtrl, wxControl);
+IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent); 
+DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED); 
+
+//uma is for wxMacFSSpec
+#ifdef __WXMAC__
+#include "wx/mac/uma.h"
+#include <Movies.h>
+#include <Gestalt.h>
+#else
+//quicktime media layer for mac emulation on pc
+#include <qtml.h>
+#endif
+
+#include <QuickTimeComponents.h>
+
+#ifdef __WXMAC__
+#define MSWMOVIECHECK
+#else
+#define MSWMOVIECHECK if(!m_bLoaded) return 0;
+#endif
+
+//Time between timer calls
+#define MOVIE_DELAY 50
+
+// ------------------------------------------------------------------
+//          wxQTTimer - Handle Asyncronous Playing
+// ------------------------------------------------------------------
+class _wxQTTimer : public wxTimer
+{
+public:
+    _wxQTTimer(Movie movie, wxMediaCtrl* parent) :
+        m_movie(movie), m_bPaused(false), m_parent(parent)
+    {
+    }
+
+    ~_wxQTTimer()
+    {
+    }
+
+    bool GetPaused() {return m_bPaused;}
+    void SetPaused(bool bPaused) {m_bPaused = bPaused;}
+
+    void Notify()
+    {
+        if (!m_bPaused)
+        {
+            if(!IsMovieDone(m_movie))
+                MoviesTask(m_movie, MOVIE_DELAY); //Give QT time to play movie
+            else
+            {
+                Stop();
+                m_parent->Stop();
+                wxASSERT(::GetMoviesError() == noErr);
+                wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED, m_parent->GetId());
+                m_parent->GetParent()->ProcessEvent(theEvent);
+            }
+        }
+    }
+
+protected:
+    Movie m_movie;
+    bool m_bPaused;
+    wxMediaCtrl* m_parent;
+};
+
+//Determines whether version 6 of QT is installed
+Boolean _wxIsQuickTime4Installed (void)
+{
+#ifdef __WXMAC__
+    short error;
+    long result;
+
+    error = Gestalt (gestaltQuickTime, &result);
+    return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0400);
+#else
+    return true;
+#endif
+}
+
+bool wxMediaCtrl::InitQT ()
+{
+    if (_wxIsQuickTime4Installed())
+    {
+        #ifndef __WXMAC__
+        int nError;
+        //-2093 no dll
+            if ((nError = InitializeQTML(0)) != noErr)
+            {
+                wxFAIL_MSG(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError));
+            }
+        #endif
+        EnterMovies();
+        return true;
+    }
+    else
+    {
+        wxFAIL_MSG(wxT("Quicktime is not installed, or Your Version of Quicktime is <= 4."));
+        return false;
+    }
+}
+
+bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxString& fileName, 
+                         const wxPoint& pos, const wxSize& size, 
+                         long style, long WXUNUSED(driver), const wxString& name)
+{
+    if(!DoCreate(parent, id, pos, size, style, name))
+        return false;
+
+    if(!fileName.empty())
+    {
+        if (!Load(fileName))
+            return false;
+
+        if(!Play())
+            return false;
+    }
+
+    return true;
+}
+
+bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxURI& location, 
+                         const wxPoint& pos, const wxSize& size, 
+                         long style, long WXUNUSED(driver), const wxString& name)
+{
+    if(!DoCreate(parent, id, pos, size, style, name))
+        return false;
+    
+    if(!location.IsReference())
+    {
+        if (!Load(location))
+            return false;
+
+        if(!Play())
+            return false;
+    }
+
+    return true;
+}
+
+bool wxMediaCtrl::DoCreate(wxWindow* parent, wxWindowID id, 
+                         const wxPoint& pos, const wxSize& size, 
+                         long style, const wxString& name)
+{
+     //do some window stuff
+    if ( !wxControl::Create(parent, id, pos, size, 
+#ifdef __WXMAC__
+                            MacRemoveBordersFromStyle(style), 
+#else
+                            style | wxNO_BORDER, 
+#endif
+                            wxDefaultValidator, name) )
+        return false;
+
+    //Set our background color to black by default
+    SetBackgroundColour(*wxBLACK);
+
+    return true;
+}
+
+bool wxMediaCtrl::Load(const wxString& fileName)
+{
+    if(m_bLoaded)
+        Cleanup();
+
+    if ( !InitQT() )
+        return false;
+
+    OSErr err = noErr;
+    short movieResFile;
+    FSSpec sfFile;
+#ifdef __WXMAC__
+    wxMacFilename2FSSpec( fileName , &sfFile ) ;
+#else
+    if (NativePathNameToFSSpec ((char*) fileName.mb_str(), &sfFile, 0) != noErr)
+        return false;
+#endif
+    if (OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
+        return false;
+
+    short movieResID = 0;
+    Str255 movieName;
+
+    err = NewMovieFromFile (
+    &m_movie,
+    movieResFile,
+    &movieResID,
+    movieName,
+    newMovieActive,
+    NULL); //wasChanged
+
+    CloseMovieFile (movieResFile);
+
+    if (err != noErr)
+        return false;
+
+    FinishLoad();
+
+    return m_bLoaded;
+}
+
+bool wxMediaCtrl::Load(const wxURI& location)
+{
+    if(m_bLoaded)
+        Cleanup();
+
+    if ( !InitQT() )
+        return false;
+
+    wxString theURI = location.BuildURI();
+
+    OSErr err = noErr;
+
+    Handle theHandle = NewHandleClear(theURI.length() + 1);
+    wxASSERT(theHandle);
+
+    BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
+
+    //create the movie from the handle that refers to the URI
+    err = NewMovieFromDataRef(&m_movie, newMovieActive, 
+                                NULL, theHandle, 
+                                URLDataHandlerSubType);
+
+    DisposeHandle(theHandle);
+
+    if (err != noErr)
+        return false;
+
+    //preroll movie for streaming
+    //TODO:Async this?
+    TimeValue timeNow;
+    Fixed playRate;
+    timeNow = GetMovieTime(m_movie, NULL);
+    playRate = GetMoviePreferredRate(m_movie);
+    PrePrerollMovie(m_movie, timeNow, playRate, NULL, NULL);
+    PrerollMovie(m_movie, timeNow, playRate);
+    SetMovieRate(m_movie, playRate);
+
+    FinishLoad();
+
+    return m_bLoaded;
+}
+
+void wxMediaCtrl::FinishLoad()
+{
+    m_timer = new _wxQTTimer(m_movie, (wxMediaCtrl*) this);
+    wxASSERT(m_timer);
+
+    //get the real size of the movie
+    Rect outRect;
+    ::GetMovieNaturalBoundsRect (m_movie, &outRect);
+    wxASSERT(::GetMoviesError() == noErr);
+
+    m_bestSize.x = outRect.right - outRect.left;
+    m_bestSize.y = outRect.bottom - outRect.top;
+        
+    //reparent movie
+if(GetMovieIndTrackType(m_movie, 1, VisualMediaCharacteristic/*AudioMediaCharacteristic*/, movieTrackCharacteristic | movieTrackEnabledOnly) != NULL)
+    {
+
+#ifdef __WXMSW__
+    CreatePortAssociation(this->GetHWND(), NULL, 0L);
+#endif
+    SetMovieGWorld(m_movie, (CGrafPtr)
+
+#ifdef __WXMSW__
+    GetNativeWindowPort(this->GetHWND())
+#else
+    GetWindowPort((WindowRef)this->MacGetTopLevelWindowRef())
+#endif
+    , nil);
+    }
+
+//    wxPrintf(wxT("%u\n"), ::GetMovieTimeScale(m_movie));
+    //we want millisecond precision
+    ::SetMovieTimeScale(m_movie, 1000);
+    
+    m_bLoaded = (::GetMoviesError() == noErr);
+
+    //work around refresh issues
+    wxSize size = GetParent()->GetSize();
+    GetParent()->SetSize(wxSize(size.x+1, size.y+1));
+    GetParent()->Refresh();
+    GetParent()->Update();
+    GetParent()->SetSize(size);
+    GetParent()->Refresh();
+    GetParent()->Update();
+}
+
+bool wxMediaCtrl::Play()
+{
+    MSWMOVIECHECK
+    ::StartMovie(m_movie);
+    m_timer->SetPaused(false);
+    m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
+    return ::GetMoviesError() == noErr;
+}
+
+bool wxMediaCtrl::Pause()
+{
+    MSWMOVIECHECK
+    ::StopMovie(m_movie);
+    m_timer->SetPaused(true);
+    m_timer->Stop();
+    return ::GetMoviesError() == noErr;
+}
+
+bool wxMediaCtrl::Stop()
+{
+    MSWMOVIECHECK
+    m_timer->SetPaused(false);
+    m_timer->Stop();
+
+    ::StopMovie(m_movie);
+    if(::GetMoviesError() != noErr)
+        return false;
+    
+    ::GoToBeginningOfMovie(m_movie);
+    return ::GetMoviesError() == noErr;
+}
+
+double wxMediaCtrl::GetPlaybackRate()
+{
+    MSWMOVIECHECK
+    return ( ((double)::GetMovieRate(m_movie)) / 0x10000);
+}
+
+bool wxMediaCtrl::SetPlaybackRate(double dRate)
+{
+    MSWMOVIECHECK
+    ::SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
+    return ::GetMoviesError() == noErr;
+}
+
+bool wxMediaCtrl::SetPosition(long where)
+{
+    MSWMOVIECHECK
+    TimeRecord theTimeRecord;
+    memset(&theTimeRecord, 0, sizeof(TimeRecord));
+    theTimeRecord.value.lo = where;
+    theTimeRecord.scale = ::GetMovieTimeScale(m_movie);
+    theTimeRecord.base = ::GetMovieTimeBase(m_movie);
+    ::SetMovieTime(m_movie, &theTimeRecord);
+
+    if (::GetMoviesError() != noErr)
+        return false;
+
+    return true;
+}
+
+long wxMediaCtrl::GetPosition()
+{
+    MSWMOVIECHECK
+    return ::GetMovieTime(m_movie, NULL);
+}
+
+long wxMediaCtrl::GetDuration()
+{
+    MSWMOVIECHECK
+    return ::GetMovieDuration(m_movie);
+}
+
+wxMediaState wxMediaCtrl::GetState()
+{
+    if ( !m_bLoaded || (m_timer->IsRunning() == false && m_timer->GetPaused() == false) )
+        return wxMEDIASTATE_STOPPED;
+
+    if( m_timer->IsRunning() == true )
+        return wxMEDIASTATE_PLAYING;
+    else
+        return wxMEDIASTATE_PAUSED;
+}
+
+void wxMediaCtrl::Cleanup()
+{
+    delete m_timer;
+    m_timer = NULL;
+
+    StopMovie(m_movie);
+    DisposeMovie(m_movie);
+    
+    //Note that ExitMovies() is not neccessary, but
+    //the docs are fuzzy on whether or not TerminateQTML is
+    ExitMovies();
+
+#ifndef __WXMAC__
+    TerminateQTML();
+#endif
+}
+
+wxMediaCtrl::~wxMediaCtrl()
+{
+    if(m_bLoaded)
+        Cleanup();
+}
+
+wxSize wxMediaCtrl::DoGetBestSize() const
+{
+    return m_bestSize;
+}
+
+void wxMediaCtrl::DoMoveWindow(int x, int y, int w, int h)
+{
+    wxControl::DoMoveWindow(x,y,w,h);
+    
+    if(m_bLoaded)
+    {
+#ifdef __WXMAC__
+        Rect theRect = {y, x, y+h, x+w};
+#else
+        Rect theRect = {0, 0, h, w};
+#endif
+        ::SetMovieBox(m_movie, &theRect);
+        wxASSERT(::GetMoviesError() == noErr);
+    }
+}
+
+#endif //wxUSE_MOVIECTRL
diff --git a/src/msw/mediactrl.cpp b/src/msw/mediactrl.cpp
new file mode 100644 (file)
index 0000000..e68eb3f
--- /dev/null
@@ -0,0 +1,637 @@
+/////////////////////////////////////////////////////////////////////////////
+// Name:        msw/mediactrl.cpp
+// Purpose:     wxMediaCtrl MSW
+// Author:      Ryan Norton <wxprojects@comcast.net>
+// Modified by: 
+// Created:     11/07/04
+// RCS-ID:      $Id$
+// Copyright:   (c) Ryan Norton
+// Licence:     wxWindows licence
+/////////////////////////////////////////////////////////////////////////////
+
+//---------------------------------------------------------------------------
+//      Pre-wx includes
+//---------------------------------------------------------------------------
+
+//#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
+//#pragma implementation "moviectrl.h"
+//#endif
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+#pragma hdrstop
+#endif
+
+#include "wx/mediactrl.h"
+
+#if wxUSE_MEDIACTRL
+
+//###########################################################################
+//  DECLARATIONS
+//###########################################################################
+
+IMPLEMENT_CLASS(wxMediaCtrl, wxControl);
+IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent); 
+DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED); 
+
+//---------------------------------------------------------------------------
+//  wxMediaCtrlImpl
+//---------------------------------------------------------------------------
+
+class wxMediaCtrlImpl
+{
+public:
+    wxMediaCtrlImpl() : m_bLoaded(false)
+    {                                                                   }
+
+    virtual ~wxMediaCtrlImpl() 
+    {                               }
+
+    virtual bool Create(wxMediaCtrl* WXUNUSED(ctrl)) 
+    {   return false;               }
+
+    virtual bool Play() { return false; }
+    virtual bool Pause() { return false; }
+    virtual bool Stop() { return false; }
+
+    virtual bool Load(const wxString&) { return false; }
+    virtual bool Load(const wxURI&) { return false; }
+
+    virtual wxMediaState GetState() { return wxMEDIASTATE_STOPPED; }
+
+    virtual bool SetPosition(long) { return 0; }
+    virtual long GetPosition() { return 0; }
+    virtual long GetDuration() { return 0; }
+
+    virtual void DoMoveWindow(int, int, int, int) {  }
+    virtual wxSize DoGetBestSize() const { return wxSize(0,0); }
+
+    virtual double GetPlaybackRate() { return 0; }
+    virtual bool SetPlaybackRate(double) { return false; }
+    
+    virtual bool MSWWindowProc(WXUINT, WXWPARAM, WXLPARAM) { return false; }
+
+    bool IsLoaded()
+    {   return m_bLoaded;   }
+
+    bool m_bLoaded;
+};
+
+//---------------------------------------------------------------------------
+//  wxDXMediaCtrlImpl
+//---------------------------------------------------------------------------
+
+#if wxUSE_DIRECTSHOW
+
+#include <dshow.h>
+
+#define WM_GRAPHNOTIFY  WM_USER+13
+
+#ifdef __WXDEBUG__
+#define wxDSVERIFY(x) wxASSERT( SUCCEEDED ((x)) )
+#else
+#define wxDSVERIFY(x) (x)
+#endif
+
+class wxDXMediaCtrlImpl : public wxMediaCtrlImpl
+{
+public:
+    wxDXMediaCtrlImpl();
+
+    virtual ~wxDXMediaCtrlImpl();
+
+    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);
+
+    void Cleanup();
+
+    bool m_bVideo;
+
+    bool MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
+
+    wxMediaCtrl* m_ctrl;
+
+    IGraphBuilder* m_pGB;
+    IMediaControl* m_pMC;
+    IMediaEventEx* m_pME;
+    IVideoWindow* m_pVW;
+    IBasicAudio* m_pBA;
+    IBasicVideo* m_pBV;
+    IMediaSeeking* m_pMS;
+
+    wxSize m_bestSize;
+};
+
+#endif //wxUSE_DIRECTSHOW
+
+//---------------------------------------------------------------------------
+//  wxWMMEMediaCtrlImpl
+//---------------------------------------------------------------------------
+
+#include <mmsystem.h>
+#include <digitalv.h>
+
+class wxWMMEMediaCtrlImpl : public wxMediaCtrlImpl
+{
+public:
+/*
+    wxWMMEMediaCtrlImpl();
+    ~wxWMMEMediaCtrlImpl();
+
+
+    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);
+*/
+    MCIDEVICEID m_hDev;
+};
+
+
+//###########################################################################
+//
+//  IMPLEMENTATION
+//
+//###########################################################################
+
+//---------------------------------------------------------------------------
+//
+//  wxMediaCtrl
+//
+//---------------------------------------------------------------------------
+
+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 ^ wxBORDER_MASK) | wxCLIP_CHILDREN, 
+                            wxDefaultValidator, name) )
+        return false;
+
+    //Set our background color to black by default
+    SetBackgroundColour(*wxBLACK);
+
+#if wxUSE_DIRECTSHOW
+    m_imp = new wxDXMediaCtrlImpl;
+    if(!m_imp->Create(this))
+    {
+        delete m_imp;
+#endif
+        m_imp = new wxWMMEMediaCtrlImpl;
+        if(!m_imp->Create(this))
+        {
+            delete m_imp;
+            m_imp = NULL;
+            return false;
+        }
+#if wxUSE_DIRECTSHOW
+    }
+#endif
+
+    if(!fileName.empty())
+    {
+        if (!Load(fileName))
+            return false;
+    }
+
+    return true;
+}
+
+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 ^ wxBORDER_MASK) | wxCLIP_CHILDREN, 
+                            wxDefaultValidator, name) )
+        return false;
+
+    //Set our background color to black by default
+    SetBackgroundColour(*wxBLACK);
+
+#if wxUSE_DIRECTSHOW
+    m_imp = new wxDXMediaCtrlImpl;
+    if(!m_imp->Create(this))
+    {
+        delete m_imp;
+#endif
+        m_imp = new wxWMMEMediaCtrlImpl;
+        if(!m_imp->Create(this))
+        {
+            delete m_imp;
+            m_imp = NULL;
+            return false;
+        }
+#if wxUSE_DIRECTSHOW
+    }
+#endif
+
+    if (!Load(location))
+        return false;
+
+    return true;
+}
+
+bool wxMediaCtrl::Load(const wxString& fileName)
+{
+    if(m_imp)
+        return m_imp->Load(fileName);
+    return false;
+}
+
+bool wxMediaCtrl::Load(const wxURI& location)
+{
+    if(m_imp)
+        return m_imp->Load(location);
+    return false;
+}
+
+bool wxMediaCtrl::Play()
+{
+    if(m_imp && m_imp->IsLoaded())
+        return m_imp->Play();
+    return false;
+}
+
+bool wxMediaCtrl::Pause()
+{
+    if(m_imp && m_imp->IsLoaded())
+        return m_imp->Pause();
+    return false;
+}
+
+bool wxMediaCtrl::Stop()
+{
+    if(m_imp && m_imp->IsLoaded())
+        return m_imp->Stop();
+    return false;
+}
+
+double wxMediaCtrl::GetPlaybackRate()
+{
+    if(m_imp && m_imp->IsLoaded())
+        return m_imp->GetPlaybackRate();
+    return 0;
+}
+
+bool wxMediaCtrl::SetPlaybackRate(double dRate)
+{
+    if(m_imp && m_imp->IsLoaded())
+        return m_imp->SetPlaybackRate(dRate);
+    return false;
+}
+
+bool wxMediaCtrl::SetPosition(long where)
+{
+    if(m_imp && m_imp->IsLoaded())
+        return m_imp->SetPosition(where);
+    return false;
+}
+
+long wxMediaCtrl::GetPosition()
+{
+    if(m_imp && m_imp->IsLoaded())
+        return m_imp->GetPosition();
+    return 0;
+}
+
+long wxMediaCtrl::GetDuration()
+{
+    if(m_imp && m_imp->IsLoaded())
+        return m_imp->GetDuration();
+    return 0;
+}
+
+wxMediaState wxMediaCtrl::GetState()
+{
+    if(m_imp && m_imp->IsLoaded())
+        return m_imp->GetState();
+    return wxMEDIASTATE_STOPPED;
+}
+
+WXLRESULT wxMediaCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+{
+    if(m_imp && m_imp->IsLoaded() && m_imp->MSWWindowProc(nMsg, wParam, lParam) )
+           return wxControl::MSWDefWindowProc(nMsg, wParam, lParam);
+    //pass the event to our parent
+    return wxControl::MSWWindowProc(nMsg, wParam, lParam);
+}
+
+wxSize wxMediaCtrl::DoGetBestSize() const
+{
+    if(m_imp && m_imp->IsLoaded())
+        return m_imp->DoGetBestSize();
+    return wxSize(0,0);
+}
+
+void wxMediaCtrl::DoMoveWindow(int x, int y, int w, int h)
+{
+    wxControl::DoMoveWindow(x,y,w,h);
+
+    if(m_imp && m_imp->IsLoaded())
+        m_imp->DoMoveWindow(x, y, w, h);
+}
+
+wxMediaCtrl::~wxMediaCtrl()
+{
+    if (m_imp)
+        delete m_imp;
+}
+
+
+//---------------------------------------------------------------------------
+//
+//  wxDXMediaCtrlImpl
+//
+//---------------------------------------------------------------------------
+
+#if wxUSE_DIRECTSHOW 
+
+wxDXMediaCtrlImpl::wxDXMediaCtrlImpl() : m_pGB(NULL)
+{
+}
+
+bool wxDXMediaCtrlImpl::Create(wxMediaCtrl* ctrl)
+{
+    //create our filter graph
+   HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
+                      IID_IGraphBuilder, (void**)&m_pGB);
+
+   //directshow not installed?
+    if ( FAILED(hr) )
+        return false;
+
+    m_ctrl = ctrl;
+
+    return true;
+}
+
+#define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; }
+
+bool wxDXMediaCtrlImpl::Load(const wxString& fileName)
+{
+    if(m_bLoaded)
+        Cleanup();                        
+        
+    SAFE_RELEASE(m_pGB);
+
+    CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
+                      IID_IGraphBuilder, (void**)&m_pGB);
+
+    //load the graph & render 
+    if( FAILED(m_pGB->RenderFile(fileName.wc_str(wxConvLocal), NULL)) )
+        return false;
+
+    //get the interfaces, all of them
+    wxDSVERIFY( m_pGB->QueryInterface(IID_IMediaControl, (void**)&m_pMC) );
+    wxDSVERIFY( m_pGB->QueryInterface(IID_IMediaEventEx, (void**)&m_pME) );
+    wxDSVERIFY( m_pGB->QueryInterface(IID_IMediaSeeking, (void**)&m_pMS) );
+    wxDSVERIFY( m_pGB->QueryInterface(IID_IVideoWindow, (void**)&m_pVW) );
+    wxDSVERIFY( m_pGB->QueryInterface(IID_IBasicAudio, (void**)&m_pBA) );
+    wxDSVERIFY( m_pGB->QueryInterface(IID_IBasicVideo, (void**)&m_pBV) );
+
+    //long lVolume;
+    //pBA->get_Volume(&lVolume);
+    //E_NOTIMPL
+
+    //get the _actual_ size of the movie & remember it
+    long nX, nY, nSX, nSY;
+    if (FAILED(m_pVW->GetWindowPosition(&nX,&nY,&nSX,&nSY)))
+    {
+        m_bVideo = false;
+
+        nSX = nSY = 0;
+    }
+    else 
+    {
+        m_bVideo = true;
+    }
+
+    m_bestSize.x = nSX;
+    m_bestSize.y = nSY;
+
+    if (m_bVideo)
+    {
+        wxDSVERIFY( m_pVW->put_Owner((OAHWND)m_ctrl->GetHandle()) );
+        wxDSVERIFY( m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS) );
+        wxDSVERIFY( m_pVW->put_Visible(OATRUE) ); //OATRUE == -1
+    }
+
+    //make it so that wxEVT_MOVIE_FINISHED works
+    wxDSVERIFY( m_pME->SetNotifyWindow((OAHWND)m_ctrl->GetHandle(), WM_GRAPHNOTIFY, 0) );
+
+    //set the time format
+    wxDSVERIFY( m_pMS->SetTimeFormat(&TIME_FORMAT_MEDIA_TIME) );
+
+    //work around refresh issues
+    wxSize size = m_ctrl->GetParent()->GetSize();
+    m_ctrl->GetParent()->SetSize(wxSize(size.x+1, size.y+1));
+    m_ctrl->GetParent()->Refresh();
+    m_ctrl->GetParent()->Update();
+    m_ctrl->GetParent()->SetSize(size);
+    m_ctrl->GetParent()->Refresh();
+    m_ctrl->GetParent()->Update();
+
+    m_bLoaded = true;
+    return true;
+}
+
+bool wxDXMediaCtrlImpl::Load(const wxURI& location)
+{
+    return Load(location.BuildUnescapedURI());
+}
+
+bool wxDXMediaCtrlImpl::Play()
+{
+    return SUCCEEDED( m_pMC->Run() );
+}
+
+bool wxDXMediaCtrlImpl::Pause()
+{
+    return SUCCEEDED( m_pMC->Pause() );
+}
+
+bool wxDXMediaCtrlImpl::Stop()
+{
+    return SUCCEEDED( m_pMC->Stop() ) && SetPosition(0);
+}
+
+bool wxDXMediaCtrlImpl::SetPosition(long where)
+{
+    //DS uses 100 nanos - so we need a 10 mult
+    LONGLONG pos = ((LONGLONG)where) * 10000;
+
+    return SUCCEEDED( m_pMS->SetPositions(
+                                &pos, 
+                                AM_SEEKING_AbsolutePositioning,
+                                NULL, 
+                                AM_SEEKING_NoPositioning
+                                    ) );
+}
+
+long wxDXMediaCtrlImpl::GetPosition()
+{
+    LONGLONG outCur, outStop;
+    wxDSVERIFY( m_pMS->GetPositions(&outCur, &outStop) );
+
+    //h,m,s,milli - outdur is in 100 nanos
+    return outCur/10000;
+}
+
+long wxDXMediaCtrlImpl::GetDuration()
+{
+    LONGLONG outDuration;
+    wxDSVERIFY( m_pMS->GetDuration(&outDuration) );
+
+    //h,m,s,milli - outdur is in 100 nanos
+    return outDuration/10000;
+}
+
+wxMediaState wxDXMediaCtrlImpl::GetState()
+{
+    //TODO: MS recommends against INFINITE here - do it in stages
+    HRESULT hr;
+    OAFilterState theState;
+    hr = m_pMC->GetState(INFINITE, &theState);
+    
+    wxASSERT( SUCCEEDED(hr) );
+
+    //MSW state is the same as ours
+    //State_Stopped   = 0,
+    //State_Paused    = State_Stopped + 1,
+    //State_Running   = State_Paused + 1
+
+    return (wxMediaState) theState;
+}
+
+double wxDXMediaCtrlImpl::GetPlaybackRate()
+{
+    double dRate;
+    wxDSVERIFY( m_pMS->GetRate(&dRate) );
+    return dRate;
+}
+
+bool wxDXMediaCtrlImpl::SetPlaybackRate(double dRate)
+{
+    return SUCCEEDED( m_pMS->SetRate(dRate) );
+}
+
+bool wxDXMediaCtrlImpl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+{
+    if (nMsg == WM_GRAPHNOTIFY)
+    {
+        LONG evCode, evParam1, evParam2;
+        HRESULT hr=S_OK;
+
+        // Process all queued events
+        while(SUCCEEDED(m_pME->GetEvent(&evCode, (LONG_PTR *) &evParam1,
+                                       (LONG_PTR *) &evParam2, 0) 
+                       ) 
+             )
+        {
+            // Free memory associated with callback, since we're not using it
+            hr = m_pME->FreeEventParams(evCode, evParam1, evParam2);
+
+            // If this is the end of the clip, notify handler
+            if(EC_COMPLETE == evCode)
+            {
+#ifdef __WXDEBUG__
+                wxASSERT( Stop() );
+#else
+                Stop();
+#endif
+                wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED, m_ctrl->GetId());
+                m_ctrl->GetParent()->ProcessEvent(theEvent);
+            }
+        }    
+        return true;
+    }
+    return false;
+}
+
+void wxDXMediaCtrlImpl::Cleanup()
+{
+    // Hide then disown the window
+    if(m_pVW)
+    {
+        m_pVW->put_Visible(OAFALSE); //OSFALSE == 0
+        m_pVW->put_Owner(NULL);
+    }
+
+    // Release and zero DirectShow interfaces
+    SAFE_RELEASE(m_pME);
+    SAFE_RELEASE(m_pMS);
+    SAFE_RELEASE(m_pMC);
+    SAFE_RELEASE(m_pBA);
+    SAFE_RELEASE(m_pBV);
+    SAFE_RELEASE(m_pVW);
+}
+
+wxDXMediaCtrlImpl::~wxDXMediaCtrlImpl()
+{
+    if (m_bLoaded)
+        Cleanup();
+
+    SAFE_RELEASE(m_pGB);
+}
+
+wxSize wxDXMediaCtrlImpl::DoGetBestSize() const
+{
+    return m_bestSize;
+}
+
+void wxDXMediaCtrlImpl::DoMoveWindow(int x, int y, int w, int h)
+{
+    if(m_bLoaded && m_bVideo)
+    {
+        wxDSVERIFY( m_pVW->SetWindowPosition(0, 0, w, h) );
+    }
+}
+
+#endif //wxUSE_DIRECTSHOW
+
+//---------------------------------------------------------------------------
+//
+//  wxWMMEMediaCtrlImpl
+//
+//---------------------------------------------------------------------------
+
+
+#endif //wxUSE_MEDIACTRL
\ No newline at end of file