]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/mediactrl.mm
wiring OnInit on osx to a later point in event processing
[wxWidgets.git] / src / osx / cocoa / mediactrl.mm
CommitLineData
38e4bfde
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/cocoa/mediactrl.cpp
3// Purpose: Built-in Media Backends for Cocoa
4// Author: Ryan Norton <wxprojects@comcast.net>
5// Modified by:
6// Created: 02/03/05
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/////////////////////////////////////////////////////////////////////////////
11
12//===========================================================================
13// DECLARATIONS
14//===========================================================================
15
16//---------------------------------------------------------------------------
17// Pre-compiled header stuff
18//---------------------------------------------------------------------------
19
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24#pragma hdrstop
25#endif
26
27//---------------------------------------------------------------------------
28// Compilation guard
29//---------------------------------------------------------------------------
30#if wxUSE_MEDIACTRL
31
32#include "wx/mediactrl.h"
33
34#ifndef WX_PRECOMP
35 #include "wx/timer.h"
36#endif
37
38#include "wx/osx/private.h"
39
40//===========================================================================
41// BACKEND DECLARATIONS
42//===========================================================================
43
44//---------------------------------------------------------------------------
45//
46// wxQTMediaBackend
47//
48//---------------------------------------------------------------------------
49
50//---------------------------------------------------------------------------
51// QT Includes
52//---------------------------------------------------------------------------
53#include <QTKit/QTKit.h>
54
55#include "wx/cocoa/autorelease.h"
56#include "wx/cocoa/string.h"
57
c560088c 58class WXDLLIMPEXP_FWD_MEDIA wxQTMediaBackend;
38e4bfde 59
c560088c
SC
60@interface wxQTMovie : QTMovie {
61
62 wxQTMediaBackend* m_backend;
63}
64
65-(BOOL)isPlaying;
66
67@end
68
69class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
38e4bfde
SC
70{
71public:
72
73 wxQTMediaBackend();
74 ~wxQTMediaBackend();
75
76 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
77 wxWindowID id,
78 const wxPoint& pos,
79 const wxSize& size,
80 long style,
81 const wxValidator& validator,
82 const wxString& name);
83
84 virtual bool Play();
85 virtual bool Pause();
86 virtual bool Stop();
87
88 virtual bool Load(const wxString& fileName);
89 virtual bool Load(const wxURI& location);
90
91 virtual wxMediaState GetState();
92
93 virtual bool SetPosition(wxLongLong where);
94 virtual wxLongLong GetPosition();
95 virtual wxLongLong GetDuration();
96
97 virtual void Move(int x, int y, int w, int h);
98 wxSize GetVideoSize() const;
99
100 virtual double GetPlaybackRate();
101 virtual bool SetPlaybackRate(double dRate);
102
103 virtual double GetVolume();
104 virtual bool SetVolume(double dVolume);
105
106 void Cleanup();
107 void FinishLoad();
108
109 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
110private:
111 void DoShowPlayerControls(wxMediaCtrlPlayerControls flags);
112
113 wxSize m_bestSize; //Original movie size
c560088c 114 wxQTMovie* m_movie; //QTMovie handle/instance
38e4bfde 115 QTMovieView* m_movieview; //QTMovieView instance
38e4bfde
SC
116
117 wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags
118
119 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
120};
121
c560088c
SC
122// --------------------------------------------------------------------------
123// wxQTMovie
124// --------------------------------------------------------------------------
38e4bfde 125
c560088c 126@implementation wxQTMovie
38e4bfde 127
c560088c
SC
128- (id)initWithURL:(NSURL *)url error:(NSError **)errorPtr
129{
130 if ( [super initWithURL:url error:errorPtr] != nil )
131 {
132 m_backend = NULL;
133
134 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
135 [nc addObserver:self selector:@selector(movieDidEnd:)
136 name:QTMovieDidEndNotification object:nil];
137 [nc addObserver:self selector:@selector(movieRateChanged:)
138 name:QTMovieRateDidChangeNotification object:nil];
139 [nc addObserver:self selector:@selector(loadStateChanged:)
140 name:QTMovieLoadStateDidChangeNotification object:nil];
141
142 return self;
143 }
144 else
145 return nil;
146}
38e4bfde 147
c560088c
SC
148-(void)dealloc
149{
150 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
151 [nc removeObserver:self];
152
153 [super dealloc];
154}
38e4bfde 155
c560088c 156-(wxQTMediaBackend*) backend;
38e4bfde 157{
c560088c
SC
158 return m_backend;
159}
160
161-(void) setBackend:(wxQTMediaBackend*) backend
162{
163 m_backend = backend;
164}
165
166- (void)movieDidEnd:(NSNotification *)notification
167{
168 if ( m_backend )
38e4bfde 169 {
c560088c
SC
170 if ( m_backend->SendStopEvent() )
171 m_backend->QueueFinishEvent();
38e4bfde 172 }
c560088c 173}
38e4bfde 174
c560088c
SC
175- (void)movieRateChanged:(NSNotification *)notification
176{
177 NSDictionary *userInfo = [notification userInfo];
178
179 NSNumber *newRate = [userInfo objectForKey:QTMovieRateDidChangeNotificationParameter];
180
181 if ([newRate intValue] == 0)
182 {
183 m_backend->QueuePauseEvent();
184 }
185 else if ( [self isPlaying] == NO )
38e4bfde 186 {
c560088c 187 m_backend->QueuePlayEvent();
38e4bfde 188 }
c560088c 189}
38e4bfde 190
0a898d4c 191-(void)loadStateChanged:(NSNotification *)notification
c560088c 192{
0a898d4c 193 QTMovie *movie = [notification object];
c560088c 194 long loadState = [[movie attributeForKey:QTMovieLoadStateAttribute] longValue];
0d505680 195 if ( loadState == QTMovieLoadStateError )
38e4bfde 196 {
0d505680 197 // error occurred
c560088c 198 }
0d505680 199 else if (loadState >= QTMovieLoadStatePlayable)
c560088c 200 {
0d505680 201 // the movie has loaded enough media data to begin playing, but we don't have an event for that yet
38e4bfde 202 }
0d505680 203 else if (loadState >= QTMovieLoadStateComplete) // we might use QTMovieLoadStatePlaythroughOK
c560088c 204 {
0d505680 205 m_backend->FinishLoad();
c560088c
SC
206 }
207}
38e4bfde 208
c560088c
SC
209-(BOOL)isPlaying
210{
211 if ([self rate] == 0)
212 {
213 return NO;
214 }
215
216 return YES;
217}
218
219@end
220
221// --------------------------------------------------------------------------
222// wxQTMediaBackend
223// --------------------------------------------------------------------------
224
225IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
38e4bfde 226
38e4bfde 227wxQTMediaBackend::wxQTMediaBackend() :
0d505680
SC
228 m_movie(nil), m_movieview(nil),
229 m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE)
38e4bfde
SC
230{
231}
232
38e4bfde
SC
233wxQTMediaBackend::~wxQTMediaBackend()
234{
c560088c 235 Cleanup();
38e4bfde
SC
236}
237
38e4bfde
SC
238bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
239 wxWindowID wid,
240 const wxPoint& pos,
241 const wxSize& size,
242 long style,
243 const wxValidator& validator,
244 const wxString& name)
245{
246 wxMediaCtrl* mediactrl = (wxMediaCtrl*) inctrl;
247
c560088c
SC
248 mediactrl->DontCreatePeer();
249
38e4bfde
SC
250 if ( !mediactrl->wxControl::Create(
251 parent, wid, pos, size,
252 wxWindow::MacRemoveBordersFromStyle(style),
253 validator, name))
254 {
255 return false;
256 }
257
258 NSRect r = wxOSXGetFrameForControl( mediactrl, pos , size ) ;
259 QTMovieView* theView = [[QTMovieView alloc] initWithFrame: r];
260
261 wxWidgetCocoaImpl* impl = new wxWidgetCocoaImpl(mediactrl,theView);
262 mediactrl->SetPeer(impl);
263
264 m_movieview = theView;
265 // will be set up after load
266 [theView setControllerVisible:NO];
267
268 m_ctrl = mediactrl;
269 return true;
270}
271
272bool wxQTMediaBackend::Load(const wxString& fileName)
273{
274 return Load(
275 wxURI(
276 wxString( wxT("file://") ) + fileName
277 )
278 );
279}
280
281bool wxQTMediaBackend::Load(const wxURI& location)
282{
c560088c 283 wxCFStringRef uri(location.BuildURI());
0a898d4c
RD
284 NSURL *url = [NSURL URLWithString: uri.AsNSString()];
285
286 if (! [wxQTMovie canInitWithURL:url])
287 return false;
38e4bfde 288
0a898d4c
RD
289 [m_movie release];
290 wxQTMovie* movie = [[wxQTMovie alloc] initWithURL:url error: nil ];
291
c560088c 292 m_movie = movie;
0a898d4c
RD
293 if (movie != nil)
294 {
295 [m_movie setBackend:this];
296 [m_movieview setMovie:movie];
297
298 // If the media file is able to be loaded quickly then there may not be
299 // any QTMovieLoadStateDidChangeNotification message sent, so we need to
300 // also check the load state here and finish our initialization if it has
301 // been loaded.
302 long loadState = [[m_movie attributeForKey:QTMovieLoadStateAttribute] longValue];
0d505680 303 if (loadState >= QTMovieLoadStateComplete)
0a898d4c
RD
304 {
305 FinishLoad();
306 }
307 }
38e4bfde 308
38e4bfde
SC
309 return movie != nil;
310}
311
312void wxQTMediaBackend::FinishLoad()
313{
c560088c
SC
314 DoShowPlayerControls(m_interfaceflags);
315
0a898d4c
RD
316 NSSize s = [[m_movie attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
317 m_bestSize = wxSize(s.width, s.height);
c560088c
SC
318
319 NotifyMovieLoaded();
38e4bfde
SC
320}
321
322bool wxQTMediaBackend::Play()
323{
324 [m_movieview play:nil];
325 return true;
326}
327
328bool wxQTMediaBackend::Pause()
329{
330 [m_movieview pause:nil];
331 return true;
332}
333
334bool wxQTMediaBackend::Stop()
335{
336 [m_movieview pause:nil];
337 [m_movieview gotoBeginning:nil];
338 return true;
339}
340
341double wxQTMediaBackend::GetVolume()
342{
343 return [m_movie volume];
344}
345
346bool wxQTMediaBackend::SetVolume(double dVolume)
347{
348 [m_movie setVolume:dVolume];
349 return true;
350}
351double wxQTMediaBackend::GetPlaybackRate()
352{
353 return [m_movie rate];
354}
355
356bool wxQTMediaBackend::SetPlaybackRate(double dRate)
357{
358 [m_movie setRate:dRate];
359 return true;
360}
361
362bool wxQTMediaBackend::SetPosition(wxLongLong where)
363{
364 QTTime position;
365 position = [m_movie currentTime];
366 position.timeValue = (where.GetValue() / 1000.0) * position.timeScale;
367 [m_movie setCurrentTime:position];
368 return true;
369}
370
371wxLongLong wxQTMediaBackend::GetPosition()
372{
373 QTTime position = [m_movie currentTime];
374 return ((double) position.timeValue) / position.timeScale * 1000;
375}
376
377wxLongLong wxQTMediaBackend::GetDuration()
378{
379 QTTime duration = [m_movie duration];
380 return ((double) duration.timeValue) / duration.timeScale * 1000;
381}
382
383wxMediaState wxQTMediaBackend::GetState()
384{
c560088c 385 if ( [m_movie isPlaying] )
38e4bfde
SC
386 return wxMEDIASTATE_PLAYING;
387 else
c560088c
SC
388 {
389 if ( GetPosition() == 0 )
390 return wxMEDIASTATE_STOPPED;
391 else
392 return wxMEDIASTATE_PAUSED;
393 }
38e4bfde
SC
394}
395
396void wxQTMediaBackend::Cleanup()
397{
38e4bfde 398 [m_movieview setMovie:NULL];
c560088c
SC
399 [m_movie release];
400 m_movie = nil;
38e4bfde
SC
401}
402
403wxSize wxQTMediaBackend::GetVideoSize() const
404{
405 return m_bestSize;
406}
407
408void wxQTMediaBackend::Move(int x, int y, int w, int h)
409{
0d505680 410 // as we have a native player, no need to move the video area
38e4bfde
SC
411}
412
413bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
414{
415 if ( m_interfaceflags != flags )
416 DoShowPlayerControls(flags);
417
418 m_interfaceflags = flags;
419 return true;
420}
421
422void wxQTMediaBackend::DoShowPlayerControls(wxMediaCtrlPlayerControls flags)
423{
424 if (flags == wxMEDIACTRLPLAYERCONTROLS_NONE )
425 {
426 [m_movieview setControllerVisible:NO];
427 }
428 else
429 {
0d505680
SC
430 [m_movieview setControllerVisible:YES];
431
38e4bfde
SC
432 [m_movieview setStepButtonsVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ? YES:NO];
433 [m_movieview setVolumeButtonVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ? YES:NO];
434 }
435}
436
437//in source file that contains stuff you don't directly use
438#include "wx/html/forcelnk.h"
439FORCE_LINK_ME(basewxmediabackends);
440
441#endif //wxUSE_MEDIACTRL