]> git.saurik.com Git - wxWidgets.git/blobdiff - src/osx/cocoa/mediactrl.mm
Fix harmless unused parameter warning in wxOSX.
[wxWidgets.git] / src / osx / cocoa / mediactrl.mm
index 274f20d7cfd7efefa5d2ab95573dc2714319c511..7faa4bc3a26891654e29716f6f286634322286e5 100644 (file)
 #include "wx/cocoa/autorelease.h"
 #include "wx/cocoa/string.h"
 
-#import <AppKit/NSMovie.h>
-#import <AppKit/NSMovieView.h>
+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];
     }