/////////////////////////////////////////////////////////////////////////////
-// Name: mac/cocoa/mediactrl.cpp
+// Name: src/cocoa/mediactrl.mm
// Purpose: Built-in Media Backends for Cocoa
// Author: Ryan Norton <wxprojects@comcast.net>
// Modified by:
// Pre-compiled header stuff
//---------------------------------------------------------------------------
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-#pragma implementation "mediactrl.h"
-#endif
-
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#pragma hdrstop
#endif
-//---------------------------------------------------------------------------
-// Includes
-//---------------------------------------------------------------------------
-#include "wx/mediactrl.h"
-
//---------------------------------------------------------------------------
// Compilation guard
//---------------------------------------------------------------------------
#if wxUSE_MEDIACTRL
+#include "wx/mediactrl.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/timer.h"
+#endif
+
//===========================================================================
// BACKEND DECLARATIONS
//===========================================================================
wxQTMediaBackend();
~wxQTMediaBackend();
- virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
+ virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
wxWindowID id,
- const wxPoint& pos,
+ const wxPoint& pos,
const wxSize& size,
- long style,
+ long style,
const wxValidator& validator,
const wxString& name);
void FinishLoad();
wxSize m_bestSize; //Original movie size
- Movie m_movie; //QT Movie handle/instance
+ Movie m_movie; //QT Movie handle/instance
NSMovieView* m_movieview; //NSMovieView instance
wxControl* m_ctrl; //Parent control
bool m_bVideo; //Whether or not we have video
+ class _wxQTTimer* m_timer; //Timer for streaming the movie
DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
};
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// wxQTMediaBackend
-//
+//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
+//Time between timer calls
+#define MOVIE_DELAY 100
+
+// --------------------------------------------------------------------------
+// wxQTTimer - Handle Asyncronous Playing
+// --------------------------------------------------------------------------
+class _wxQTTimer : public wxTimer
+{
+public:
+ _wxQTTimer(Movie movie, wxQTMediaBackend* parent) :
+ m_movie(movie), m_bPaused(false), m_parent(parent)
+ {
+ }
+
+ ~_wxQTTimer()
+ {
+ }
+
+ bool GetPaused() {return m_bPaused;}
+ void SetPaused(bool bPaused) {m_bPaused = bPaused;}
+
+ //-----------------------------------------------------------------------
+ // _wxQTTimer::Notify
+ //
+ // 1) Checks to see if the movie is done, and if not continues
+ // streaming the movie
+ // 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of
+ // the movie.
+ //-----------------------------------------------------------------------
+ void Notify()
+ {
+ if (!m_bPaused)
+ {
+ if(!IsMovieDone(m_movie))
+ MoviesTask(m_movie, MOVIE_DELAY);
+ else
+ {
+ wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
+ m_parent->m_ctrl->GetId());
+ m_parent->m_ctrl->ProcessEvent(theEvent);
+
+ if(theEvent.IsAllowed())
+ {
+ Stop();
+ m_parent->Stop();
+ wxASSERT(::GetMoviesError() == noErr);
+
+ //send the event to our child
+ wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
+ m_parent->m_ctrl->GetId());
+ m_parent->m_ctrl->ProcessEvent(theEvent);
+ }
+ }
+ }
+ }
+
+protected:
+ Movie m_movie; //Our movie instance
+ bool m_bPaused; //Whether we are paused or not
+ wxQTMediaBackend* m_parent; //Backend pointer
+};
+
//---------------------------------------------------------------------------
// wxQTMediaBackend Constructor
//
// Sets m_timer to NULL signifying we havn't loaded anything yet
//---------------------------------------------------------------------------
-wxQTMediaBackend::wxQTMediaBackend()
+wxQTMediaBackend::wxQTMediaBackend() : m_timer(NULL)
{
}
//---------------------------------------------------------------------------
wxQTMediaBackend::~wxQTMediaBackend()
{
- Cleanup();
+ if(m_timer)
+ Cleanup();
- //Note that ExitMovies() is not neccessary...
- ::ExitMovies();
+ //Note that ExitMovies() is not necessary...
+ ExitMovies();
}
//---------------------------------------------------------------------------
// 1) Intializes QuickTime
// 2) Creates the control window
//---------------------------------------------------------------------------
-bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
+bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
wxWindowID wid,
- const wxPoint& pos,
+ const wxPoint& pos,
const wxSize& size,
- long style,
+ long style,
const wxValidator& validator,
const wxString& name)
{
EnterMovies();
-
+
wxMediaCtrl* ctrl = (wxMediaCtrl*) inctrl;
//Create the control base
wxASSERT(ctrl->CreateBase(parent,wid,pos,size,style, validator, name));
-
+
//Create the NSMovieView
ctrl->SetNSView(NULL);
NSMovieView* theView = [[NSMovieView alloc] initWithFrame: ctrl->MakeDefaultNSRect(size)];
parent->CocoaAddChild(ctrl);
ctrl->SetInitialFrameRect(pos,size);
}
-
+
[theView showController:false adjustingSize:true];
m_movieview = theView;
m_ctrl = ctrl;
{
return Load(
wxURI(
- wxString( wxT("file://") ) + fileName
+ wxString( wxT("file://") ) + fileName
)
);
}
//---------------------------------------------------------------------------
bool wxQTMediaBackend::Load(const wxURI& location)
{
- Cleanup();
+ if(m_timer)
+ Cleanup();
wxString theURI = location.BuildURI();
m_movie = (Movie) [[m_movieview movie] QTMovie];
+ //preroll movie for streaming
+ //TODO:Async this using threads?
+ 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 ::GetMoviesError() == noErr;
//---------------------------------------------------------------------------
// wxQTMediaBackend::FinishLoad
+//
+// 1) Create the movie timer
+// 2) Get real size of movie for GetBestSize/sizers
+// 3) See if there is video in the movie, and if so then either
+// SetMovieGWorld if < 10.2 or use Native CreateMovieControl
+// 4) Set the movie time scale to something usable so that seeking
+// etc. will work correctly
+// 5) Refresh parent window
//---------------------------------------------------------------------------
void wxQTMediaBackend::FinishLoad()
{
+ m_timer = new _wxQTTimer(m_movie, (wxQTMediaBackend*) this);
+ wxASSERT(m_timer);
+
//get the real size of the movie
Rect outRect;
::GetMovieNaturalBoundsRect (m_movie, &outRect);
//
//Here, if the parent of the control has a sizer - we
//tell it to recalculate the size of this control since
- //the user opened a seperate media file
+ //the user opened a separate media file
//
m_ctrl->InvalidateBestSize();
m_ctrl->GetParent()->Layout();
//---------------------------------------------------------------------------
bool wxQTMediaBackend::Play()
{
- [m_movieview start:NULL];
+ ::StartMovie(m_movie);
+ m_timer->SetPaused(false);
+ m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
return ::GetMoviesError() == noErr;
}
//---------------------------------------------------------------------------
bool wxQTMediaBackend::Pause()
{
- [m_movieview stop:NULL];
+ ::StopMovie(m_movie);
+ m_timer->SetPaused(true);
+ m_timer->Stop();
return ::GetMoviesError() == noErr;
}
//---------------------------------------------------------------------------
bool wxQTMediaBackend::Stop()
{
- [m_movieview stop:NULL];
- [m_movieview gotoBeginning:NULL];
+ m_timer->SetPaused(false);
+ m_timer->Stop();
+
+ ::StopMovie(m_movie);
+ if(::GetMoviesError() != noErr)
+ return false;
+
+ ::GoToBeginningOfMovie(m_movie);
return ::GetMoviesError() == noErr;
}
//---------------------------------------------------------------------------
wxMediaState wxQTMediaBackend::GetState()
{
- if ( [m_movieview isPlaying] )
- return wxMEDIASTATE_PLAYING;
-
- if( wxQTMediaBackend::GetPosition() == 0 )
+ if ( !m_timer || (m_timer->IsRunning() == false &&
+ m_timer->GetPaused() == false) )
return wxMEDIASTATE_STOPPED;
+
+ if( m_timer->IsRunning() == true )
+ return wxMEDIASTATE_PLAYING;
else
return wxMEDIASTATE_PAUSED;
}
//---------------------------------------------------------------------------
void wxQTMediaBackend::Cleanup()
{
- if([m_movieview movie])
- {
- [[m_movieview movie] release];
- [m_movieview setMovie:NULL];
- }
+ delete m_timer;
+ m_timer = NULL;
+
+ [[m_movieview movie] release];
+ [m_movieview setMovie:NULL];
}
//---------------------------------------------------------------------------
//in source file that contains stuff you don't directly use
-#include <wx/html/forcelnk.h>
+#include "wx/html/forcelnk.h"
FORCE_LINK_ME(basewxmediabackends);
#endif //wxUSE_MEDIACTRL
-
-
-
-
-