base wxMediaCtrl files

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@30443 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Ryan Norton
2004-11-11 05:21:02 +00:00
parent 17a7bf57f8
commit 1a680109ac
5 changed files with 1325 additions and 0 deletions

View File

@@ -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

18
include/wx/mediactrl.h Normal file
View File

@@ -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

104
include/wx/msw/mediactrl.h Normal file
View File

@@ -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

View File

@@ -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

637
src/msw/mediactrl.cpp Normal file
View File

@@ -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