X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/38e4bfde171ed2ea63c0aeacb7b921f8983b7211..a51e79e87db3512823258d487849bb7e7947b700:/src/osx/cocoa/mediactrl.mm diff --git a/src/osx/cocoa/mediactrl.mm b/src/osx/cocoa/mediactrl.mm index 274f20d7cf..7faa4bc3a2 100644 --- a/src/osx/cocoa/mediactrl.mm +++ b/src/osx/cocoa/mediactrl.mm @@ -55,11 +55,18 @@ #include "wx/cocoa/autorelease.h" #include "wx/cocoa/string.h" -#import -#import +class WXDLLIMPEXP_FWD_MEDIA wxQTMediaBackend; +@interface wxQTMovie : QTMovie { + + wxQTMediaBackend* m_backend; +} + +-(BOOL)isPlaying; -class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend +@end + +class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase { public: @@ -104,119 +111,130 @@ private: void DoShowPlayerControls(wxMediaCtrlPlayerControls flags); wxSize m_bestSize; //Original movie size - QTMovie* m_movie; //QTMovie handle/instance + wxQTMovie* m_movie; //QTMovie handle/instance QTMovieView* m_movieview; //QTMovieView instance - wxControl* m_ctrl; //Parent control wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags DECLARE_DYNAMIC_CLASS(wxQTMediaBackend); }; +// -------------------------------------------------------------------------- +// wxQTMovie +// -------------------------------------------------------------------------- -//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -// -// wxQTMediaBackend -// -//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +@implementation wxQTMovie -IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend); +- (id)initWithURL:(NSURL *)url error:(NSError **)errorPtr +{ + if ( [super initWithURL:url error:errorPtr] != nil ) + { + m_backend = NULL; + + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self selector:@selector(movieDidEnd:) + name:QTMovieDidEndNotification object:nil]; + [nc addObserver:self selector:@selector(movieRateChanged:) + name:QTMovieRateDidChangeNotification object:nil]; + [nc addObserver:self selector:@selector(loadStateChanged:) + name:QTMovieLoadStateDidChangeNotification object:nil]; + + return self; + } + else + return nil; +} -//Time between timer calls -#define MOVIE_DELAY 100 +-(void)dealloc +{ + NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; + [nc removeObserver:self]; + + [super dealloc]; +} -// -------------------------------------------------------------------------- -// wxQTTimer - Handle Asyncronous Playing -// -------------------------------------------------------------------------- -class _wxQTTimer : public wxTimer +-(wxQTMediaBackend*) backend; { -public: - _wxQTTimer(QTMovie movie, wxQTMediaBackend* parent) : - m_movie(movie), m_bPaused(false), m_parent(parent) + return m_backend; +} + +-(void) setBackend:(wxQTMediaBackend*) backend +{ + m_backend = backend; +} + +- (void)movieDidEnd:(NSNotification *)notification +{ + if ( m_backend ) { + if ( m_backend->SendStopEvent() ) + m_backend->QueueFinishEvent(); } +} - ~_wxQTTimer() +- (void)movieRateChanged:(NSNotification *)notification +{ + NSDictionary *userInfo = [notification userInfo]; + + NSNumber *newRate = [userInfo objectForKey:QTMovieRateDidChangeNotificationParameter]; + + if ([newRate intValue] == 0) + { + m_backend->QueuePauseEvent(); + } + else if ( [self isPlaying] == NO ) { + m_backend->QueuePlayEvent(); } +} - 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() +-(void)loadStateChanged:(NSNotification *)notification +{ + QTMovie *movie = [notification object]; + long loadState = [[movie attributeForKey:QTMovieLoadStateAttribute] longValue]; + if ( loadState == QTMovieLoadStateError ) { -#if 0 - 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->GetEventHandler()->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->GetEventHandler()->ProcessEvent(theEvent); - } - } - } -#endif + // error occurred + } + else if (loadState >= QTMovieLoadStatePlayable) + { + // the movie has loaded enough media data to begin playing, but we don't have an event for that yet + } + else if (loadState >= QTMovieLoadStateComplete) // we might use QTMovieLoadStatePlaythroughOK + { + m_backend->FinishLoad(); } +} -protected: - QTMovie m_movie; //Our movie instance - bool m_bPaused; //Whether we are paused or not - wxQTMediaBackend* m_parent; //Backend pointer -}; +-(BOOL)isPlaying +{ + if ([self rate] == 0) + { + return NO; + } + + return YES; +} + +@end + +// -------------------------------------------------------------------------- +// wxQTMediaBackend +// -------------------------------------------------------------------------- + +IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend); -//--------------------------------------------------------------------------- -// wxQTMediaBackend Constructor -// -// Sets m_timer to NULL signifying we havn't loaded anything yet -//--------------------------------------------------------------------------- wxQTMediaBackend::wxQTMediaBackend() : - m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE), - m_movie(nil), m_movieview(nil), m_ctrl(NULL) + m_movie(nil), m_movieview(nil), + m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE) { } -//--------------------------------------------------------------------------- -// 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() { - [m_movie release]; + Cleanup(); } -//--------------------------------------------------------------------------- -// wxQTMediaBackend::CreateControl -// -// 1) Intializes QuickTime -// 2) Creates the control window -//--------------------------------------------------------------------------- bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent, wxWindowID wid, const wxPoint& pos, @@ -227,14 +245,8 @@ bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent, { wxMediaCtrl* mediactrl = (wxMediaCtrl*) inctrl; - // - // 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 - // + mediactrl->DontCreatePeer(); + if ( !mediactrl->wxControl::Create( parent, wid, pos, size, wxWindow::MacRemoveBordersFromStyle(style), @@ -268,32 +280,43 @@ bool wxQTMediaBackend::Load(const wxString& fileName) bool wxQTMediaBackend::Load(const wxURI& location) { - wxString theURI = location.BuildURI(); - - QTMovie* movie = [[QTMovie alloc] initWithURL: [NSURL URLWithString: wxNSStringWithWxString(theURI)] error: nil ]; - - [m_movie release]; - m_movie = movie; + wxCFStringRef uri(location.BuildURI()); + NSURL *url = [NSURL URLWithString: uri.AsNSString()]; - [m_movieview setMovie:movie]; + if (! [wxQTMovie canInitWithURL:url]) + return false; - DoShowPlayerControls(m_interfaceflags); - - FinishLoad(); + [m_movie release]; + wxQTMovie* movie = [[wxQTMovie alloc] initWithURL:url error: nil ]; + m_movie = movie; + if (movie != nil) + { + [m_movie setBackend:this]; + [m_movieview setMovie:movie]; + + // If the media file is able to be loaded quickly then there may not be + // any QTMovieLoadStateDidChangeNotification message sent, so we need to + // also check the load state here and finish our initialization if it has + // been loaded. + long loadState = [[m_movie attributeForKey:QTMovieLoadStateAttribute] longValue]; + if (loadState >= QTMovieLoadStateComplete) + { + FinishLoad(); + } + } + return movie != nil; } void wxQTMediaBackend::FinishLoad() { - NSRect r =[m_movieview movieBounds]; - m_bestSize.x = r.size.width; - m_bestSize.y = r.size.height; - - m_ctrl->InvalidateBestSize(); - m_ctrl->GetParent()->Layout(); - m_ctrl->GetParent()->Refresh(); - m_ctrl->GetParent()->Update(); + DoShowPlayerControls(m_interfaceflags); + + NSSize s = [[m_movie attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]; + m_bestSize = wxSize(s.width, s.height); + + NotifyMovieLoaded(); } bool wxQTMediaBackend::Play() @@ -359,22 +382,22 @@ wxLongLong wxQTMediaBackend::GetDuration() wxMediaState wxQTMediaBackend::GetState() { - /* - if ( !m_timer || (m_timer->IsRunning() == false && - m_timer->GetPaused() == false) ) - return wxMEDIASTATE_STOPPED; - - if( m_timer->IsRunning() == true ) + if ( [m_movie isPlaying] ) return wxMEDIASTATE_PLAYING; else - */ - return wxMEDIASTATE_PAUSED; + { + if ( GetPosition() == 0 ) + return wxMEDIASTATE_STOPPED; + else + return wxMEDIASTATE_PAUSED; + } } void wxQTMediaBackend::Cleanup() { - [[m_movieview movie] release]; [m_movieview setMovie:NULL]; + [m_movie release]; + m_movie = nil; } wxSize wxQTMediaBackend::GetVideoSize() const @@ -384,6 +407,7 @@ wxSize wxQTMediaBackend::GetVideoSize() const void wxQTMediaBackend::Move(int x, int y, int w, int h) { + // as we have a native player, no need to move the video area } bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags) @@ -403,6 +427,8 @@ void wxQTMediaBackend::DoShowPlayerControls(wxMediaCtrlPlayerControls flags) } else { + [m_movieview setControllerVisible:YES]; + [m_movieview setStepButtonsVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ? YES:NO]; [m_movieview setVolumeButtonVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ? YES:NO]; }