--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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
--- /dev/null
+/////////////////////////////////////////////////////////////////////////////
+// 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