From 0b6d471427717055bcc483a244311687d603a0a6 Mon Sep 17 00:00:00 2001 From: Ryan Norton Date: Fri, 4 Feb 2005 17:56:49 +0000 Subject: [PATCH] fix cocoa wxTimer Stop crash, proper autorelease stuff in cocoa wxtimer, use our own custom c implementation for cocoa wxMediaCtrl because NSMovieView implementation isnt very good git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@31753 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/cocoa/mediactrl.mm | 139 ++++++++++++++++++++++++++++++++++------- src/cocoa/timer.mm | 10 ++- 2 files changed, 125 insertions(+), 24 deletions(-) diff --git a/src/cocoa/mediactrl.mm b/src/cocoa/mediactrl.mm index f350636a95..bbbd81a75c 100644 --- a/src/cocoa/mediactrl.mm +++ b/src/cocoa/mediactrl.mm @@ -51,6 +51,7 @@ //--------------------------------------------------------------------------- // QT Includes //--------------------------------------------------------------------------- +#include "wx/timer.h" #include #include "wx/cocoa/autorelease.h" @@ -102,6 +103,7 @@ public: 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); }; @@ -115,12 +117,74 @@ public: 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 +199,11 @@ wxQTMediaBackend::wxQTMediaBackend() //--------------------------------------------------------------------------- wxQTMediaBackend::~wxQTMediaBackend() { - Cleanup(); + if(m_timer) + Cleanup(); //Note that ExitMovies() is not neccessary... - ::ExitMovies(); + ExitMovies(); } //--------------------------------------------------------------------------- @@ -174,7 +239,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; @@ -203,7 +268,8 @@ bool wxQTMediaBackend::Load(const wxString& fileName) //--------------------------------------------------------------------------- bool wxQTMediaBackend::Load(const wxURI& location) { - Cleanup(); + if(m_timer) + Cleanup(); wxString theURI = location.BuildURI(); @@ -212,6 +278,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 +295,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); @@ -253,7 +340,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 +354,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 +369,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 +450,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 +468,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]; } //--------------------------------------------------------------------------- @@ -402,8 +500,3 @@ void wxQTMediaBackend::Move(int x, int y, int w, int h) FORCE_LINK_ME(basewxmediabackends); #endif //wxUSE_MEDIACTRL - - - - - diff --git a/src/cocoa/timer.mm b/src/cocoa/timer.mm index ad99c3227a..9cef73ce20 100644 --- a/src/cocoa/timer.mm +++ b/src/cocoa/timer.mm @@ -26,6 +26,8 @@ #include "wx/timer.h" #endif +#include "wx/cocoa/autorelease.h" + #import // ============================================================================ @@ -94,6 +96,10 @@ void wxTimer::Init() bool wxTimer::Start(int millisecs, bool oneShot) { + Stop(); + + wxAutoNSAutoreleasePool thePool; + m_cocoaNSTimer = [[NSTimer scheduledTimerWithTimeInterval: millisecs / 1000.0 //seconds target: wxTimer::sm_cocoaDelegate @@ -108,9 +114,11 @@ void wxTimer::Stop() { if (m_cocoaNSTimer) { + NSObject* theUserInfo = [m_cocoaNSTimer userInfo]; [m_cocoaNSTimer invalidate]; - [[m_cocoaNSTimer userInfo] release]; + [theUserInfo release]; [m_cocoaNSTimer release]; + m_cocoaNSTimer = NULL; } } -- 2.45.2