From 1a680109ac733a9bebfa08a614c1e22735fda2d9 Mon Sep 17 00:00:00 2001 From: Ryan Norton Date: Thu, 11 Nov 2004 05:21:02 +0000 Subject: [PATCH] base wxMediaCtrl files git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30443 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/mac/carbon/mediactrl.h | 120 ++++++ include/wx/mediactrl.h | 18 + include/wx/msw/mediactrl.h | 104 +++++ src/mac/carbon/mediactrl.cpp | 446 +++++++++++++++++++++ src/msw/mediactrl.cpp | 637 ++++++++++++++++++++++++++++++ 5 files changed, 1325 insertions(+) create mode 100644 include/wx/mac/carbon/mediactrl.h create mode 100644 include/wx/mediactrl.h create mode 100644 include/wx/msw/mediactrl.h create mode 100644 src/mac/carbon/mediactrl.cpp create mode 100644 src/msw/mediactrl.cpp diff --git a/include/wx/mac/carbon/mediactrl.h b/include/wx/mac/carbon/mediactrl.h new file mode 100644 index 0000000000..b2a5681329 --- /dev/null +++ b/include/wx/mac/carbon/mediactrl.h @@ -0,0 +1,120 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/msw/moviectrl.h +// Purpose: wxMediaCtrl mac +// Author: Ryan Norton +// 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 index 0000000000..8836ab9777 --- /dev/null +++ b/include/wx/mediactrl.h @@ -0,0 +1,18 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/mediactrl.h +// Purpose: wxMediaCtrl class +// Author: Ryan Norton +// 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 index 0000000000..9c59d05dfc --- /dev/null +++ b/include/wx/msw/mediactrl.h @@ -0,0 +1,104 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: wx/msw/mediactrl.h +// Purpose: DirectX7+ wxMediaCtrl MSW +// Author: Ryan Norton +// 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 index 0000000000..8d7644e2bb --- /dev/null +++ b/src/mac/carbon/mediactrl.cpp @@ -0,0 +1,446 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: mac/carbon/moviectrl.cpp +// Purpose: wxMediaCtrl MAC CARBON QT +// Author: Ryan Norton +// 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 +#include +#else +//quicktime media layer for mac emulation on pc +#include +#endif + +#include + +#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 index 0000000000..e68eb3f08e --- /dev/null +++ b/src/msw/mediactrl.cpp @@ -0,0 +1,637 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: msw/mediactrl.cpp +// Purpose: wxMediaCtrl MSW +// Author: Ryan Norton +// 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 + +#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 +#include + +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 -- 2.45.2