+#if wxUSE_QUICKTIME
+
+IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
+
+//Time between timer calls
+#define MOVIE_DELAY 100
+
+#include "wx/timer.h"
+
+// --------------------------------------------------------------------------
+// wxQTTimer - Handle Asyncronous Playing
+// --------------------------------------------------------------------------
+class _wxQTTimer : public wxTimer
+{
+public:
+ _wxQTTimer(Movie movie, wxQTMediaBackend* parent, wxQuickTimeLibrary* pLib) :
+ m_movie(movie), m_bPaused(false), m_parent(parent), m_pLib(pLib)
+ {
+ }
+
+ ~_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(!m_pLib->IsMovieDone(m_movie))
+ m_pLib->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(m_pLib->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
+ wxQuickTimeLibrary* m_pLib; //Interfaces
+};
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend Destructor
+//
+// Sets m_timer to NULL signifying we havn't loaded anything yet
+//---------------------------------------------------------------------------
+wxQTMediaBackend::wxQTMediaBackend() : m_timer(NULL)
+{
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend Destructor
+//
+// 1) Cleans up the QuickTime movie instance
+// 2) Decrements the QuickTime reference counter - if this reaches
+// 0, QuickTime shuts down
+// 3) Decrements the QuickTime Windows Media Layer reference counter -
+// if this reaches 0, QuickTime shuts down the Windows Media Layer
+//---------------------------------------------------------------------------
+wxQTMediaBackend::~wxQTMediaBackend()
+{
+ if(m_timer)
+ Cleanup();
+
+ if(m_lib.IsOk())
+ {
+ //Note that ExitMovies() is not neccessary, but
+ //the docs are fuzzy on whether or not TerminateQTML is
+ m_lib.ExitMovies();
+ m_lib.TerminateQTML();
+ }
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::CreateControl
+//
+// 1) Intializes QuickTime
+// 2) Creates the control window
+//---------------------------------------------------------------------------
+bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent,
+ wxWindowID id,
+ const wxPoint& pos,
+ const wxSize& size,
+ long style,
+ const wxValidator& validator,
+ const wxString& name)
+{
+ if(!m_lib.Initialize())
+ return false;
+
+ int nError;
+ if ((nError = m_lib.InitializeQTML(0)) != noErr) //-2093 no dll
+ {
+ wxFAIL_MSG(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError));
+ return false;
+ }
+ m_lib.EnterMovies();
+
+ //
+ // Create window
+ // By default wxWindow(s) is created with a border -
+ // so we need to get rid of those
+ //
+ // Since we don't have a child window like most other
+ // backends, we don't need wxCLIP_CHILDREN
+ //
+ if ( !ctrl->wxControl::Create(parent, id, pos, size,
+ (style & ~wxBORDER_MASK) | wxBORDER_NONE,
+ validator, name) )
+ return false;
+
+ m_ctrl = ctrl;
+ return true;
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Load (file version)
+//
+// 1) Get an FSSpec from the Windows path name
+// 2) Open the movie
+// 3) Obtain the movie instance from the movie resource
+// 4)
+//---------------------------------------------------------------------------
+bool wxQTMediaBackend::Load(const wxString& fileName)
+{
+ if(m_timer)
+ Cleanup();
+
+ OSErr err = noErr;
+ short movieResFile;
+ FSSpec sfFile;
+
+ if (m_lib.NativePathNameToFSSpec ((char*) (const char*) fileName.mb_str(),
+ &sfFile, 0) != noErr)
+ return false;
+
+ if (m_lib.OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
+ return false;
+
+ short movieResID = 0;
+ Str255 movieName;
+
+ err = m_lib.NewMovieFromFile (
+ &m_movie,
+ movieResFile,
+ &movieResID,
+ movieName,
+ newMovieActive,
+ NULL); //wasChanged
+
+ m_lib.CloseMovieFile (movieResFile);
+
+ if (err != noErr)
+ return false;
+
+ FinishLoad();
+
+ return m_lib.GetMoviesError() == noErr;
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+bool wxQTMediaBackend::Load(const wxURI& location)
+{
+ if(m_timer)
+ Cleanup();
+
+ wxString theURI = location.BuildURI();
+
+ OSErr err = noErr;
+
+ Handle theHandle = m_lib.NewHandleClear(theURI.length() + 1);
+ wxASSERT(theHandle);
+
+ m_lib.BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
+
+ //create the movie from the handle that refers to the URI
+ err = m_lib.NewMovieFromDataRef(&m_movie, newMovieActive,
+ NULL, theHandle,
+ 'url'); //URLDataHandlerSubType
+
+ m_lib.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);
+ m_lib.SetMovieRate(m_movie, playRate);
+*/
+
+ FinishLoad();
+
+ return m_lib.GetMoviesError() == noErr;
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+void wxQTMediaBackend::FinishLoad()
+{
+ m_timer = new _wxQTTimer(m_movie, (wxQTMediaBackend*) this, &m_lib);
+ wxASSERT(m_timer);
+
+ //get the real size of the movie
+ Rect outRect;
+ m_lib.GetMovieNaturalBoundsRect (m_movie, &outRect);
+ wxASSERT(m_lib.GetMoviesError() == noErr);
+
+ m_bestSize.x = outRect.right - outRect.left;
+ m_bestSize.y = outRect.bottom - outRect.top;
+
+ //reparent movie/*AudioMediaCharacteristic*/
+ if(m_lib.GetMovieIndTrackType(m_movie, 1,
+ 'eyes', //VisualMediaCharacteristic,
+ (1 << 1) //movieTrackCharacteristic
+ | (1 << 2) //movieTrackEnabledOnly
+ ) != NULL)
+ {
+ m_lib.CreatePortAssociation(m_ctrl->GetHWND(), NULL, 0L);
+
+ m_lib.SetMovieGWorld(m_movie,
+ (CGrafPtr) m_lib.GetNativeWindowPort(m_ctrl->GetHWND()),
+ NULL);
+ }
+
+ //we want millisecond precision
+ m_lib.SetMovieTimeScale(m_movie, 1000);
+ wxASSERT(m_lib.GetMoviesError() == noErr);
+
+ //
+ //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
+ //
+ m_ctrl->InvalidateBestSize();
+ m_ctrl->GetParent()->Layout();
+ m_ctrl->GetParent()->Refresh();
+ m_ctrl->GetParent()->Update();
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+bool wxQTMediaBackend::Play()
+{
+ m_lib.StartMovie(m_movie);
+ m_timer->SetPaused(false);
+ m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
+ return m_lib.GetMoviesError() == noErr;
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+bool wxQTMediaBackend::Pause()
+{
+ m_lib.StopMovie(m_movie);
+ m_timer->SetPaused(true);
+ m_timer->Stop();
+ return m_lib.GetMoviesError() == noErr;
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+bool wxQTMediaBackend::Stop()
+{
+ m_timer->SetPaused(false);
+ m_timer->Stop();
+
+ m_lib.StopMovie(m_movie);
+ if(m_lib.GetMoviesError() != noErr)
+ return false;
+
+ m_lib.GoToBeginningOfMovie(m_movie);
+ return m_lib.GetMoviesError() == noErr;
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+double wxQTMediaBackend::GetPlaybackRate()
+{
+ return ( ((double)m_lib.GetMovieRate(m_movie)) / 0x10000);
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+bool wxQTMediaBackend::SetPlaybackRate(double dRate)
+{
+ m_lib.SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
+ return m_lib.GetMoviesError() == noErr;
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+bool wxQTMediaBackend::SetPosition(wxLongLong where)
+{
+ TimeRecord theTimeRecord;
+ memset(&theTimeRecord, 0, sizeof(TimeRecord));
+ theTimeRecord.value.lo = where.GetValue();
+ theTimeRecord.scale = m_lib.GetMovieTimeScale(m_movie);
+ theTimeRecord.base = m_lib.GetMovieTimeBase(m_movie);
+ m_lib.SetMovieTime(m_movie, &theTimeRecord);
+
+ if (m_lib.GetMoviesError() != noErr)
+ return false;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::GetPosition
+//
+// 1) Calls GetMovieTime to get the position we are in in the movie
+// in milliseconds (we called
+//---------------------------------------------------------------------------
+wxLongLong wxQTMediaBackend::GetPosition()
+{
+ return m_lib.GetMovieTime(m_movie, NULL);
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+wxLongLong wxQTMediaBackend::GetDuration()
+{
+ return m_lib.GetMovieDuration(m_movie);
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+wxMediaState wxQTMediaBackend::GetState()
+{
+ 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;
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+void wxQTMediaBackend::Cleanup()
+{
+ delete m_timer;
+ m_timer = NULL;
+
+ m_lib.StopMovie(m_movie);
+ m_lib.DisposeMovie(m_movie);
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+wxSize wxQTMediaBackend::GetVideoSize() const
+{
+ return m_bestSize;
+}
+
+//---------------------------------------------------------------------------
+// wxQTMediaBackend::Move
+//
+// TODO
+//---------------------------------------------------------------------------
+void wxQTMediaBackend::Move(int WXUNUSED(x), int WXUNUSED(y), int w, int h)
+{
+ if(m_timer)
+ {
+ Rect theRect = {0, 0, h, w};
+
+ m_lib.SetMovieBox(m_movie, &theRect);
+ wxASSERT(m_lib.GetMoviesError() == noErr);
+ }
+}
+
+//---------------------------------------------------------------------------
+// End QT Compilation Guard
+//---------------------------------------------------------------------------
+#endif //wxUSE_QUICKTIME
+
+//in source file that contains stuff you don't directly use
+#include <wx/html/forcelnk.h>
+FORCE_LINK_ME(basewxmediabackends);
+
+//---------------------------------------------------------------------------
+// End wxMediaCtrl Compilation Guard and this file
+//---------------------------------------------------------------------------