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
This commit is contained in:
@@ -51,6 +51,7 @@
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// QT Includes
|
// QT Includes
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
#include "wx/timer.h"
|
||||||
#include <QuickTime/QuickTime.h>
|
#include <QuickTime/QuickTime.h>
|
||||||
|
|
||||||
#include "wx/cocoa/autorelease.h"
|
#include "wx/cocoa/autorelease.h"
|
||||||
@@ -102,6 +103,7 @@ public:
|
|||||||
NSMovieView* m_movieview; //NSMovieView instance
|
NSMovieView* m_movieview; //NSMovieView instance
|
||||||
wxControl* m_ctrl; //Parent control
|
wxControl* m_ctrl; //Parent control
|
||||||
bool m_bVideo; //Whether or not we have video
|
bool m_bVideo; //Whether or not we have video
|
||||||
|
class _wxQTTimer* m_timer; //Timer for streaming the movie
|
||||||
|
|
||||||
DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
|
DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
|
||||||
};
|
};
|
||||||
@@ -115,12 +117,74 @@ public:
|
|||||||
|
|
||||||
IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
|
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
|
// wxQTMediaBackend Constructor
|
||||||
//
|
//
|
||||||
// Sets m_timer to NULL signifying we havn't loaded anything yet
|
// 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()
|
wxQTMediaBackend::~wxQTMediaBackend()
|
||||||
{
|
{
|
||||||
|
if(m_timer)
|
||||||
Cleanup();
|
Cleanup();
|
||||||
|
|
||||||
//Note that ExitMovies() is not neccessary...
|
//Note that ExitMovies() is not neccessary...
|
||||||
::ExitMovies();
|
ExitMovies();
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -203,6 +268,7 @@ bool wxQTMediaBackend::Load(const wxString& fileName)
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
bool wxQTMediaBackend::Load(const wxURI& location)
|
bool wxQTMediaBackend::Load(const wxURI& location)
|
||||||
{
|
{
|
||||||
|
if(m_timer)
|
||||||
Cleanup();
|
Cleanup();
|
||||||
|
|
||||||
wxString theURI = location.BuildURI();
|
wxString theURI = location.BuildURI();
|
||||||
@@ -212,6 +278,16 @@ bool wxQTMediaBackend::Load(const wxURI& location)
|
|||||||
|
|
||||||
m_movie = (Movie) [[m_movieview movie] QTMovie];
|
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();
|
FinishLoad();
|
||||||
|
|
||||||
return ::GetMoviesError() == noErr;
|
return ::GetMoviesError() == noErr;
|
||||||
@@ -219,9 +295,20 @@ bool wxQTMediaBackend::Load(const wxURI& location)
|
|||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// wxQTMediaBackend::FinishLoad
|
// 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()
|
void wxQTMediaBackend::FinishLoad()
|
||||||
{
|
{
|
||||||
|
m_timer = new _wxQTTimer(m_movie, (wxQTMediaBackend*) this);
|
||||||
|
wxASSERT(m_timer);
|
||||||
|
|
||||||
//get the real size of the movie
|
//get the real size of the movie
|
||||||
Rect outRect;
|
Rect outRect;
|
||||||
::GetMovieNaturalBoundsRect (m_movie, &outRect);
|
::GetMovieNaturalBoundsRect (m_movie, &outRect);
|
||||||
@@ -253,7 +340,9 @@ void wxQTMediaBackend::FinishLoad()
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
bool wxQTMediaBackend::Play()
|
bool wxQTMediaBackend::Play()
|
||||||
{
|
{
|
||||||
[m_movieview start:NULL];
|
::StartMovie(m_movie);
|
||||||
|
m_timer->SetPaused(false);
|
||||||
|
m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
|
||||||
return ::GetMoviesError() == noErr;
|
return ::GetMoviesError() == noErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +354,9 @@ bool wxQTMediaBackend::Play()
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
bool wxQTMediaBackend::Pause()
|
bool wxQTMediaBackend::Pause()
|
||||||
{
|
{
|
||||||
[m_movieview stop:NULL];
|
::StopMovie(m_movie);
|
||||||
|
m_timer->SetPaused(true);
|
||||||
|
m_timer->Stop();
|
||||||
return ::GetMoviesError() == noErr;
|
return ::GetMoviesError() == noErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,8 +369,14 @@ bool wxQTMediaBackend::Pause()
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
bool wxQTMediaBackend::Stop()
|
bool wxQTMediaBackend::Stop()
|
||||||
{
|
{
|
||||||
[m_movieview stop:NULL];
|
m_timer->SetPaused(false);
|
||||||
[m_movieview gotoBeginning:NULL];
|
m_timer->Stop();
|
||||||
|
|
||||||
|
::StopMovie(m_movie);
|
||||||
|
if(::GetMoviesError() != noErr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
::GoToBeginningOfMovie(m_movie);
|
||||||
return ::GetMoviesError() == noErr;
|
return ::GetMoviesError() == noErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,11 +450,12 @@ wxLongLong wxQTMediaBackend::GetDuration()
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
wxMediaState wxQTMediaBackend::GetState()
|
wxMediaState wxQTMediaBackend::GetState()
|
||||||
{
|
{
|
||||||
if ( [m_movieview isPlaying] )
|
if ( !m_timer || (m_timer->IsRunning() == false &&
|
||||||
return wxMEDIASTATE_PLAYING;
|
m_timer->GetPaused() == false) )
|
||||||
|
|
||||||
if( wxQTMediaBackend::GetPosition() == 0 )
|
|
||||||
return wxMEDIASTATE_STOPPED;
|
return wxMEDIASTATE_STOPPED;
|
||||||
|
|
||||||
|
if( m_timer->IsRunning() == true )
|
||||||
|
return wxMEDIASTATE_PLAYING;
|
||||||
else
|
else
|
||||||
return wxMEDIASTATE_PAUSED;
|
return wxMEDIASTATE_PAUSED;
|
||||||
}
|
}
|
||||||
@@ -370,11 +468,11 @@ wxMediaState wxQTMediaBackend::GetState()
|
|||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void wxQTMediaBackend::Cleanup()
|
void wxQTMediaBackend::Cleanup()
|
||||||
{
|
{
|
||||||
if([m_movieview movie])
|
delete m_timer;
|
||||||
{
|
m_timer = NULL;
|
||||||
|
|
||||||
[[m_movieview movie] release];
|
[[m_movieview movie] release];
|
||||||
[m_movieview setMovie:NULL];
|
[m_movieview setMovie:NULL];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
@@ -402,8 +500,3 @@ void wxQTMediaBackend::Move(int x, int y, int w, int h)
|
|||||||
FORCE_LINK_ME(basewxmediabackends);
|
FORCE_LINK_ME(basewxmediabackends);
|
||||||
|
|
||||||
#endif //wxUSE_MEDIACTRL
|
#endif //wxUSE_MEDIACTRL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -26,6 +26,8 @@
|
|||||||
#include "wx/timer.h"
|
#include "wx/timer.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "wx/cocoa/autorelease.h"
|
||||||
|
|
||||||
#import <Foundation/NSTimer.h>
|
#import <Foundation/NSTimer.h>
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -94,6 +96,10 @@ void wxTimer::Init()
|
|||||||
|
|
||||||
bool wxTimer::Start(int millisecs, bool oneShot)
|
bool wxTimer::Start(int millisecs, bool oneShot)
|
||||||
{
|
{
|
||||||
|
Stop();
|
||||||
|
|
||||||
|
wxAutoNSAutoreleasePool thePool;
|
||||||
|
|
||||||
m_cocoaNSTimer = [[NSTimer
|
m_cocoaNSTimer = [[NSTimer
|
||||||
scheduledTimerWithTimeInterval: millisecs / 1000.0 //seconds
|
scheduledTimerWithTimeInterval: millisecs / 1000.0 //seconds
|
||||||
target: wxTimer::sm_cocoaDelegate
|
target: wxTimer::sm_cocoaDelegate
|
||||||
@@ -108,9 +114,11 @@ void wxTimer::Stop()
|
|||||||
{
|
{
|
||||||
if (m_cocoaNSTimer)
|
if (m_cocoaNSTimer)
|
||||||
{
|
{
|
||||||
|
NSObject* theUserInfo = [m_cocoaNSTimer userInfo];
|
||||||
[m_cocoaNSTimer invalidate];
|
[m_cocoaNSTimer invalidate];
|
||||||
[[m_cocoaNSTimer userInfo] release];
|
[theUserInfo release];
|
||||||
[m_cocoaNSTimer release];
|
[m_cocoaNSTimer release];
|
||||||
|
m_cocoaNSTimer = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user