1 /////////////////////////////////////////////////////////////////////////////
 
   2 // Name:        src/cocoa/mediactrl.cpp
 
   3 // Purpose:     Built-in Media Backends for Cocoa
 
   4 // Author:      Ryan Norton <wxprojects@comcast.net>
 
   7 // Copyright:   (c) 2004-2005 Ryan Norton, (c) 2005 David Elliot
 
   8 // Licence:     wxWindows licence
 
   9 /////////////////////////////////////////////////////////////////////////////
 
  11 //===========================================================================
 
  13 //===========================================================================
 
  15 //---------------------------------------------------------------------------
 
  16 // Pre-compiled header stuff
 
  17 //---------------------------------------------------------------------------
 
  19 // For compilers that support precompilation, includes "wx.h".
 
  20 #include "wx/wxprec.h"
 
  26 //---------------------------------------------------------------------------
 
  28 //---------------------------------------------------------------------------
 
  31 #include "wx/mediactrl.h"
 
  37 #include "wx/osx/private.h"
 
  39 //===========================================================================
 
  40 //  BACKEND DECLARATIONS
 
  41 //===========================================================================
 
  43 //---------------------------------------------------------------------------
 
  47 //---------------------------------------------------------------------------
 
  49 //---------------------------------------------------------------------------
 
  51 //---------------------------------------------------------------------------
 
  52 #include <QTKit/QTKit.h>
 
  54 #include "wx/cocoa/autorelease.h"
 
  55 #include "wx/cocoa/string.h"
 
  57 class WXDLLIMPEXP_FWD_MEDIA wxQTMediaBackend;
 
  59 @interface wxQTMovie : QTMovie {
 
  61     wxQTMediaBackend* m_backend;
 
  68 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
 
  75     virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
 
  80                                      const wxValidator& validator,
 
  81                                      const wxString& name);
 
  87     virtual bool Load(const wxString& fileName);
 
  88     virtual bool Load(const wxURI& location);
 
  90     virtual wxMediaState GetState();
 
  92     virtual bool SetPosition(wxLongLong where);
 
  93     virtual wxLongLong GetPosition();
 
  94     virtual wxLongLong GetDuration();
 
  96     virtual void Move(int x, int y, int w, int h);
 
  97     wxSize GetVideoSize() const;
 
  99     virtual double GetPlaybackRate();
 
 100     virtual bool SetPlaybackRate(double dRate);
 
 102     virtual double GetVolume();
 
 103     virtual bool SetVolume(double dVolume);
 
 108     virtual bool   ShowPlayerControls(wxMediaCtrlPlayerControls flags);
 
 110     void DoShowPlayerControls(wxMediaCtrlPlayerControls flags);
 
 112     wxSize m_bestSize;              //Original movie size
 
 113     wxQTMovie* m_movie;               //QTMovie handle/instance
 
 114     QTMovieView* m_movieview;       //QTMovieView instance
 
 116     wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags
 
 118     DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
 
 121 // --------------------------------------------------------------------------
 
 123 // --------------------------------------------------------------------------
 
 125 @implementation wxQTMovie 
 
 127 - (id)initWithURL:(NSURL *)url error:(NSError **)errorPtr
 
 129     if ( [super initWithURL:url error:errorPtr] != nil )
 
 133         NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
 
 134         [nc addObserver:self selector:@selector(movieDidEnd:) 
 
 135                    name:QTMovieDidEndNotification object:nil];
 
 136         [nc addObserver:self selector:@selector(movieRateChanged:) 
 
 137                    name:QTMovieRateDidChangeNotification object:nil];
 
 138         [nc addObserver:self selector:@selector(loadStateChanged:) 
 
 139                    name:QTMovieLoadStateDidChangeNotification object:nil];
 
 149     NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
 
 150         [nc removeObserver:self];
 
 155 -(wxQTMediaBackend*) backend;
 
 160 -(void) setBackend:(wxQTMediaBackend*) backend
 
 165 - (void)movieDidEnd:(NSNotification *)notification
 
 169         if ( m_backend->SendStopEvent() )
 
 170             m_backend->QueueFinishEvent();
 
 174 - (void)movieRateChanged:(NSNotification *)notification
 
 176         NSDictionary *userInfo = [notification userInfo];
 
 178         NSNumber *newRate = [userInfo objectForKey:QTMovieRateDidChangeNotificationParameter];
 
 180         if ([newRate intValue] == 0)
 
 182                 m_backend->QueuePauseEvent();
 
 184     else if ( [self isPlaying] == NO )
 
 186                 m_backend->QueuePlayEvent();
 
 190 -(void)loadStateChanged:(NSNotification *)notification
 
 192     QTMovie *movie = [notification object];
 
 193     long loadState = [[movie attributeForKey:QTMovieLoadStateAttribute] longValue];
 
 194     if ( loadState == QTMovieLoadStateError )
 
 198     else if (loadState >= QTMovieLoadStatePlayable)
 
 200         // the movie has loaded enough media data to begin playing, but we don't have an event for that yet
 
 202     else if (loadState >= QTMovieLoadStateComplete) // we might use QTMovieLoadStatePlaythroughOK
 
 204         m_backend->FinishLoad();
 
 210         if ([self rate] == 0)
 
 220 // --------------------------------------------------------------------------
 
 222 // --------------------------------------------------------------------------
 
 224 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
 
 226 wxQTMediaBackend::wxQTMediaBackend() : 
 
 227     m_movie(nil), m_movieview(nil),
 
 228     m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE)
 
 232 wxQTMediaBackend::~wxQTMediaBackend()
 
 237 bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
 
 242                                      const wxValidator& validator,
 
 243                                      const wxString& name)
 
 245     wxMediaCtrl* mediactrl = (wxMediaCtrl*) inctrl;
 
 247     mediactrl->DontCreatePeer();
 
 249     if ( !mediactrl->wxControl::Create(
 
 250                                        parent, wid, pos, size,
 
 251                                        wxWindow::MacRemoveBordersFromStyle(style),
 
 257     NSRect r = wxOSXGetFrameForControl( mediactrl, pos , size ) ;
 
 258     QTMovieView* theView = [[QTMovieView alloc] initWithFrame: r];
 
 260     wxWidgetCocoaImpl* impl = new wxWidgetCocoaImpl(mediactrl,theView);
 
 261     mediactrl->SetPeer(impl);
 
 263     m_movieview = theView;
 
 264     // will be set up after load
 
 265     [theView setControllerVisible:NO];
 
 271 bool wxQTMediaBackend::Load(const wxString& fileName)
 
 275                     wxString( wxT("file://") ) + fileName
 
 280 bool wxQTMediaBackend::Load(const wxURI& location)
 
 282     wxCFStringRef uri(location.BuildURI());
 
 283     NSURL *url = [NSURL URLWithString: uri.AsNSString()];
 
 285     if (! [wxQTMovie canInitWithURL:url])
 
 289     wxQTMovie* movie = [[wxQTMovie alloc] initWithURL:url error: nil ];
 
 294         [m_movie setBackend:this];
 
 295         [m_movieview setMovie:movie];
 
 297         // If the media file is able to be loaded quickly then there may not be
 
 298         // any QTMovieLoadStateDidChangeNotification message sent, so we need to
 
 299         // also check the load state here and finish our initialization if it has
 
 301         long loadState = [[m_movie attributeForKey:QTMovieLoadStateAttribute] longValue];
 
 302         if (loadState >= QTMovieLoadStateComplete)
 
 311 void wxQTMediaBackend::FinishLoad()
 
 313     DoShowPlayerControls(m_interfaceflags);
 
 315     NSSize s = [[m_movie attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
 
 316     m_bestSize = wxSize(s.width, s.height);
 
 321 bool wxQTMediaBackend::Play()
 
 323     [m_movieview play:nil];
 
 327 bool wxQTMediaBackend::Pause()
 
 329     [m_movieview pause:nil];
 
 333 bool wxQTMediaBackend::Stop()
 
 335     [m_movieview pause:nil];
 
 336     [m_movieview gotoBeginning:nil];
 
 340 double wxQTMediaBackend::GetVolume()
 
 342     return [m_movie volume];
 
 345 bool wxQTMediaBackend::SetVolume(double dVolume)
 
 347     [m_movie setVolume:dVolume];
 
 350 double wxQTMediaBackend::GetPlaybackRate()
 
 352     return [m_movie rate];
 
 355 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
 
 357     [m_movie setRate:dRate];
 
 361 bool wxQTMediaBackend::SetPosition(wxLongLong where)
 
 364     position = [m_movie currentTime];
 
 365     position.timeValue = (where.GetValue() / 1000.0) * position.timeScale;
 
 366     [m_movie setCurrentTime:position];
 
 370 wxLongLong wxQTMediaBackend::GetPosition()
 
 372     QTTime position = [m_movie currentTime];
 
 373     return ((double) position.timeValue) / position.timeScale * 1000;
 
 376 wxLongLong wxQTMediaBackend::GetDuration()
 
 378     QTTime duration = [m_movie duration];
 
 379     return ((double) duration.timeValue) / duration.timeScale * 1000;
 
 382 wxMediaState wxQTMediaBackend::GetState()
 
 384     if ( [m_movie isPlaying] )
 
 385         return wxMEDIASTATE_PLAYING;
 
 388         if ( GetPosition() == 0 )
 
 389             return wxMEDIASTATE_STOPPED;
 
 391             return wxMEDIASTATE_PAUSED;
 
 395 void wxQTMediaBackend::Cleanup()
 
 397     [m_movieview setMovie:NULL];
 
 402 wxSize wxQTMediaBackend::GetVideoSize() const
 
 407 void wxQTMediaBackend::Move(int x, int y, int w, int h)
 
 409     // as we have a native player, no need to move the video area 
 
 412 bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
 
 414     if ( m_interfaceflags != flags )
 
 415         DoShowPlayerControls(flags);
 
 417     m_interfaceflags = flags;    
 
 421 void wxQTMediaBackend::DoShowPlayerControls(wxMediaCtrlPlayerControls flags)
 
 423     if (flags == wxMEDIACTRLPLAYERCONTROLS_NONE )
 
 425         [m_movieview setControllerVisible:NO];
 
 429         [m_movieview setControllerVisible:YES];
 
 431         [m_movieview setStepButtonsVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ? YES:NO];
 
 432         [m_movieview setVolumeButtonVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ? YES:NO];
 
 436 //in source file that contains stuff you don't directly use
 
 437 #include "wx/html/forcelnk.h"
 
 438 FORCE_LINK_ME(basewxmediabackends);
 
 440 #endif //wxUSE_MEDIACTRL