1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/cocoa/mediactrl.cpp
3 // Purpose: Built-in Media Backends for Cocoa
4 // Author: Ryan Norton <wxprojects@comcast.net>
7 // RCS-ID: $Id: mediactrl.mm 39285 2006-05-23 11:04:37Z ABX $
8 // Copyright: (c) 2004-2005 Ryan Norton, (c) 2005 David Elliot
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 //===========================================================================
14 //===========================================================================
16 //---------------------------------------------------------------------------
17 // Pre-compiled header stuff
18 //---------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 //---------------------------------------------------------------------------
29 //---------------------------------------------------------------------------
32 #include "wx/mediactrl.h"
38 #include "wx/osx/private.h"
40 //===========================================================================
41 // BACKEND DECLARATIONS
42 //===========================================================================
44 //---------------------------------------------------------------------------
48 //---------------------------------------------------------------------------
50 //---------------------------------------------------------------------------
52 //---------------------------------------------------------------------------
53 #include <QTKit/QTKit.h>
55 #include "wx/cocoa/autorelease.h"
56 #include "wx/cocoa/string.h"
58 #import <AppKit/NSMovie.h>
59 #import <AppKit/NSMovieView.h>
61 class WXDLLIMPEXP_FWD_MEDIA wxQTMediaBackend;
63 @interface wxQTMovie : QTMovie {
65 wxQTMediaBackend* m_backend;
72 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
79 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
84 const wxValidator& validator,
85 const wxString& name);
91 virtual bool Load(const wxString& fileName);
92 virtual bool Load(const wxURI& location);
94 virtual wxMediaState GetState();
96 virtual bool SetPosition(wxLongLong where);
97 virtual wxLongLong GetPosition();
98 virtual wxLongLong GetDuration();
100 virtual void Move(int x, int y, int w, int h);
101 wxSize GetVideoSize() const;
103 virtual double GetPlaybackRate();
104 virtual bool SetPlaybackRate(double dRate);
106 virtual double GetVolume();
107 virtual bool SetVolume(double dVolume);
112 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
114 void DoShowPlayerControls(wxMediaCtrlPlayerControls flags);
116 wxSize m_bestSize; //Original movie size
117 wxQTMovie* m_movie; //QTMovie handle/instance
118 QTMovieView* m_movieview; //QTMovieView instance
120 wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags
122 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
125 // --------------------------------------------------------------------------
127 // --------------------------------------------------------------------------
129 @implementation wxQTMovie
131 - (id)initWithURL:(NSURL *)url error:(NSError **)errorPtr
133 if ( [super initWithURL:url error:errorPtr] != nil )
137 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
138 [nc addObserver:self selector:@selector(movieDidEnd:)
139 name:QTMovieDidEndNotification object:nil];
140 [nc addObserver:self selector:@selector(movieRateChanged:)
141 name:QTMovieRateDidChangeNotification object:nil];
142 [nc addObserver:self selector:@selector(loadStateChanged:)
143 name:QTMovieLoadStateDidChangeNotification object:nil];
153 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
154 [nc removeObserver:self];
159 -(wxQTMediaBackend*) backend;
164 -(void) setBackend:(wxQTMediaBackend*) backend
169 - (void)movieDidEnd:(NSNotification *)notification
173 if ( m_backend->SendStopEvent() )
174 m_backend->QueueFinishEvent();
178 - (void)movieRateChanged:(NSNotification *)notification
180 NSDictionary *userInfo = [notification userInfo];
182 NSNumber *newRate = [userInfo objectForKey:QTMovieRateDidChangeNotificationParameter];
184 if ([newRate intValue] == 0)
186 m_backend->QueuePauseEvent();
188 else if ( [self isPlaying] == NO )
190 m_backend->QueuePlayEvent();
194 -(void)loadStateChanged:(QTMovie *)movie
196 long loadState = [[movie attributeForKey:QTMovieLoadStateAttribute] longValue];
197 if (loadState >= QTMovieLoadStatePlayable)
199 // the movie has loaded enough media data to begin playing
201 else if (loadState >= QTMovieLoadStateLoaded)
203 m_backend->FinishLoad();
205 else if (loadState == -1)
213 if ([self rate] == 0)
223 // --------------------------------------------------------------------------
225 // --------------------------------------------------------------------------
227 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
229 wxQTMediaBackend::wxQTMediaBackend() :
230 m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE),
231 m_movie(nil), m_movieview(nil)
235 wxQTMediaBackend::~wxQTMediaBackend()
240 bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
245 const wxValidator& validator,
246 const wxString& name)
248 wxMediaCtrl* mediactrl = (wxMediaCtrl*) inctrl;
250 mediactrl->DontCreatePeer();
252 if ( !mediactrl->wxControl::Create(
253 parent, wid, pos, size,
254 wxWindow::MacRemoveBordersFromStyle(style),
260 NSRect r = wxOSXGetFrameForControl( mediactrl, pos , size ) ;
261 QTMovieView* theView = [[QTMovieView alloc] initWithFrame: r];
263 wxWidgetCocoaImpl* impl = new wxWidgetCocoaImpl(mediactrl,theView);
264 mediactrl->SetPeer(impl);
266 m_movieview = theView;
267 // will be set up after load
268 [theView setControllerVisible:NO];
274 bool wxQTMediaBackend::Load(const wxString& fileName)
278 wxString( wxT("file://") ) + fileName
283 bool wxQTMediaBackend::Load(const wxURI& location)
285 wxCFStringRef uri(location.BuildURI());
288 wxQTMovie* movie = [[wxQTMovie alloc] initWithURL: [NSURL URLWithString: uri.AsNSString()] error: nil ];
291 [m_movie setBackend:this];
292 [m_movieview setMovie:movie];
297 void wxQTMediaBackend::FinishLoad()
299 DoShowPlayerControls(m_interfaceflags);
301 NSRect r =[m_movieview movieBounds];
302 m_bestSize.x = r.size.width;
303 m_bestSize.y = r.size.height;
309 bool wxQTMediaBackend::Play()
311 [m_movieview play:nil];
315 bool wxQTMediaBackend::Pause()
317 [m_movieview pause:nil];
321 bool wxQTMediaBackend::Stop()
323 [m_movieview pause:nil];
324 [m_movieview gotoBeginning:nil];
328 double wxQTMediaBackend::GetVolume()
330 return [m_movie volume];
333 bool wxQTMediaBackend::SetVolume(double dVolume)
335 [m_movie setVolume:dVolume];
338 double wxQTMediaBackend::GetPlaybackRate()
340 return [m_movie rate];
343 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
345 [m_movie setRate:dRate];
349 bool wxQTMediaBackend::SetPosition(wxLongLong where)
352 position = [m_movie currentTime];
353 position.timeValue = (where.GetValue() / 1000.0) * position.timeScale;
354 [m_movie setCurrentTime:position];
358 wxLongLong wxQTMediaBackend::GetPosition()
360 QTTime position = [m_movie currentTime];
361 return ((double) position.timeValue) / position.timeScale * 1000;
364 wxLongLong wxQTMediaBackend::GetDuration()
366 QTTime duration = [m_movie duration];
367 return ((double) duration.timeValue) / duration.timeScale * 1000;
370 wxMediaState wxQTMediaBackend::GetState()
372 if ( [m_movie isPlaying] )
373 return wxMEDIASTATE_PLAYING;
376 if ( GetPosition() == 0 )
377 return wxMEDIASTATE_STOPPED;
379 return wxMEDIASTATE_PAUSED;
383 void wxQTMediaBackend::Cleanup()
385 [m_movieview setMovie:NULL];
390 wxSize wxQTMediaBackend::GetVideoSize() const
395 void wxQTMediaBackend::Move(int x, int y, int w, int h)
399 bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
401 if ( m_interfaceflags != flags )
402 DoShowPlayerControls(flags);
404 m_interfaceflags = flags;
408 void wxQTMediaBackend::DoShowPlayerControls(wxMediaCtrlPlayerControls flags)
410 if (flags == wxMEDIACTRLPLAYERCONTROLS_NONE )
412 [m_movieview setControllerVisible:NO];
416 [m_movieview setStepButtonsVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ? YES:NO];
417 [m_movieview setVolumeButtonVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ? YES:NO];
421 //in source file that contains stuff you don't directly use
422 #include "wx/html/forcelnk.h"
423 FORCE_LINK_ME(basewxmediabackends);
425 #endif //wxUSE_MEDIACTRL