]> git.saurik.com Git - wxWidgets.git/blobdiff - src/cocoa/mediactrl.mm
Fix referencing of cairo_t returned from wxDCImpl::GetCairoContext().
[wxWidgets.git] / src / cocoa / mediactrl.mm
index f350636a95810fec4b5ba18300a77052759dc47d..3e1a97a1d270664e35f1cfba2060776e6ae78c47 100644 (file)
@@ -1,10 +1,9 @@
 /////////////////////////////////////////////////////////////////////////////
-// 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:
 // Created:     02/03/05
-// RCS-ID:      $Id$
 // Copyright:   (c) 2004-2005 Ryan Norton, (c) 2005 David Elliot
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 // 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
 //===========================================================================
@@ -67,11 +63,11 @@ public:
     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);
 
@@ -98,10 +94,11 @@ public:
     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);
 };
@@ -110,17 +107,79 @@ public:
 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 //
 // 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)
 {
 }
 
@@ -135,10 +194,11 @@ wxQTMediaBackend::wxQTMediaBackend()
 //---------------------------------------------------------------------------
 wxQTMediaBackend::~wxQTMediaBackend()
 {
-    Cleanup();
+    if(m_timer)
+        Cleanup();
 
-    //Note that ExitMovies() is not neccessary...
-    ::ExitMovies();
+    //Note that ExitMovies() is not necessary...
+    ExitMovies();
 }
 
 //---------------------------------------------------------------------------
@@ -147,21 +207,21 @@ wxQTMediaBackend::~wxQTMediaBackend()
 // 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)];
@@ -174,7 +234,7 @@ bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
         parent->CocoaAddChild(ctrl);
         ctrl->SetInitialFrameRect(pos,size);
     }
-    
+
     [theView showController:false adjustingSize:true];
     m_movieview = theView;
     m_ctrl = ctrl;
@@ -190,7 +250,7 @@ bool wxQTMediaBackend::Load(const wxString& fileName)
 {
     return Load(
                 wxURI(
-                    wxString( wxT("file://") ) + fileName 
+                    wxString( wxT("file://") ) + fileName
                      )
                );
 }
@@ -203,7 +263,8 @@ bool wxQTMediaBackend::Load(const wxString& fileName)
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Load(const wxURI& location)
 {
-    Cleanup();
+    if(m_timer)
+        Cleanup();
 
     wxString theURI = location.BuildURI();
 
@@ -212,6 +273,16 @@ bool wxQTMediaBackend::Load(const wxURI& location)
 
     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;
@@ -219,9 +290,20 @@ bool wxQTMediaBackend::Load(const wxURI& location)
 
 //---------------------------------------------------------------------------
 // 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);
@@ -237,7 +319,7 @@ void wxQTMediaBackend::FinishLoad()
     //
     //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();
@@ -253,7 +335,9 @@ void wxQTMediaBackend::FinishLoad()
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Play()
 {
-    [m_movieview start:NULL];
+    ::StartMovie(m_movie);
+    m_timer->SetPaused(false);
+    m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
     return ::GetMoviesError() == noErr;
 }
 
@@ -265,7 +349,9 @@ bool wxQTMediaBackend::Play()
 //---------------------------------------------------------------------------
 bool wxQTMediaBackend::Pause()
 {
-    [m_movieview stop:NULL];
+    ::StopMovie(m_movie);
+    m_timer->SetPaused(true);
+    m_timer->Stop();
     return ::GetMoviesError() == noErr;
 }
 
@@ -278,8 +364,14 @@ bool wxQTMediaBackend::Pause()
 //---------------------------------------------------------------------------
 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;
 }
 
@@ -353,11 +445,12 @@ wxLongLong wxQTMediaBackend::GetDuration()
 //---------------------------------------------------------------------------
 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;
 }
@@ -370,11 +463,11 @@ wxMediaState wxQTMediaBackend::GetState()
 //---------------------------------------------------------------------------
 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];
 }
 
 //---------------------------------------------------------------------------
@@ -398,12 +491,7 @@ void wxQTMediaBackend::Move(int x, int y, int w, int h)
 
 
 //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
-
-
-
-
-