]> git.saurik.com Git - wxWidgets.git/blob - src/osx/cocoa/mediactrl.mm
Make wxEVT_CHAR_HOOK propagate upwards and send it to the window itself.
[wxWidgets.git] / src / osx / cocoa / mediactrl.mm
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
58 #import <AppKit/NSMovie.h>
59 #import <AppKit/NSMovieView.h>
60
61 class WXDLLIMPEXP_FWD_MEDIA wxQTMediaBackend;
62
63 @interface wxQTMovie : QTMovie {
64
65 wxQTMediaBackend* m_backend;
66 }
67
68 -(BOOL)isPlaying;
69
70 @end
71
72 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackendCommonBase
73 {
74 public:
75
76 wxQTMediaBackend();
77 ~wxQTMediaBackend();
78
79 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
80 wxWindowID id,
81 const wxPoint& pos,
82 const wxSize& size,
83 long style,
84 const wxValidator& validator,
85 const wxString& name);
86
87 virtual bool Play();
88 virtual bool Pause();
89 virtual bool Stop();
90
91 virtual bool Load(const wxString& fileName);
92 virtual bool Load(const wxURI& location);
93
94 virtual wxMediaState GetState();
95
96 virtual bool SetPosition(wxLongLong where);
97 virtual wxLongLong GetPosition();
98 virtual wxLongLong GetDuration();
99
100 virtual void Move(int x, int y, int w, int h);
101 wxSize GetVideoSize() const;
102
103 virtual double GetPlaybackRate();
104 virtual bool SetPlaybackRate(double dRate);
105
106 virtual double GetVolume();
107 virtual bool SetVolume(double dVolume);
108
109 void Cleanup();
110 void FinishLoad();
111
112 virtual bool ShowPlayerControls(wxMediaCtrlPlayerControls flags);
113 private:
114 void DoShowPlayerControls(wxMediaCtrlPlayerControls flags);
115
116 wxSize m_bestSize; //Original movie size
117 wxQTMovie* m_movie; //QTMovie handle/instance
118 QTMovieView* m_movieview; //QTMovieView instance
119
120 wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags
121
122 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
123 };
124
125 // --------------------------------------------------------------------------
126 // wxQTMovie
127 // --------------------------------------------------------------------------
128
129 @implementation wxQTMovie
130
131 - (id)initWithURL:(NSURL *)url error:(NSError **)errorPtr
132 {
133 if ( [super initWithURL:url error:errorPtr] != nil )
134 {
135 m_backend = NULL;
136
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];
144
145 return self;
146 }
147 else
148 return nil;
149 }
150
151 -(void)dealloc
152 {
153 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
154 [nc removeObserver:self];
155
156 [super dealloc];
157 }
158
159 -(wxQTMediaBackend*) backend;
160 {
161 return m_backend;
162 }
163
164 -(void) setBackend:(wxQTMediaBackend*) backend
165 {
166 m_backend = backend;
167 }
168
169 - (void)movieDidEnd:(NSNotification *)notification
170 {
171 if ( m_backend )
172 {
173 if ( m_backend->SendStopEvent() )
174 m_backend->QueueFinishEvent();
175 }
176 }
177
178 - (void)movieRateChanged:(NSNotification *)notification
179 {
180 NSDictionary *userInfo = [notification userInfo];
181
182 NSNumber *newRate = [userInfo objectForKey:QTMovieRateDidChangeNotificationParameter];
183
184 if ([newRate intValue] == 0)
185 {
186 m_backend->QueuePauseEvent();
187 }
188 else if ( [self isPlaying] == NO )
189 {
190 m_backend->QueuePlayEvent();
191 }
192 }
193
194 -(void)loadStateChanged:(QTMovie *)movie
195 {
196 long loadState = [[movie attributeForKey:QTMovieLoadStateAttribute] longValue];
197 if (loadState >= QTMovieLoadStatePlayable)
198 {
199 // the movie has loaded enough media data to begin playing
200 }
201 else if (loadState >= QTMovieLoadStateLoaded)
202 {
203 m_backend->FinishLoad();
204 }
205 else if (loadState == -1)
206 {
207 // error occurred
208 }
209 }
210
211 -(BOOL)isPlaying
212 {
213 if ([self rate] == 0)
214 {
215 return NO;
216 }
217
218 return YES;
219 }
220
221 @end
222
223 // --------------------------------------------------------------------------
224 // wxQTMediaBackend
225 // --------------------------------------------------------------------------
226
227 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
228
229 wxQTMediaBackend::wxQTMediaBackend() :
230 m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE),
231 m_movie(nil), m_movieview(nil)
232 {
233 }
234
235 wxQTMediaBackend::~wxQTMediaBackend()
236 {
237 Cleanup();
238 }
239
240 bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
241 wxWindowID wid,
242 const wxPoint& pos,
243 const wxSize& size,
244 long style,
245 const wxValidator& validator,
246 const wxString& name)
247 {
248 wxMediaCtrl* mediactrl = (wxMediaCtrl*) inctrl;
249
250 mediactrl->DontCreatePeer();
251
252 if ( !mediactrl->wxControl::Create(
253 parent, wid, pos, size,
254 wxWindow::MacRemoveBordersFromStyle(style),
255 validator, name))
256 {
257 return false;
258 }
259
260 NSRect r = wxOSXGetFrameForControl( mediactrl, pos , size ) ;
261 QTMovieView* theView = [[QTMovieView alloc] initWithFrame: r];
262
263 wxWidgetCocoaImpl* impl = new wxWidgetCocoaImpl(mediactrl,theView);
264 mediactrl->SetPeer(impl);
265
266 m_movieview = theView;
267 // will be set up after load
268 [theView setControllerVisible:NO];
269
270 m_ctrl = mediactrl;
271 return true;
272 }
273
274 bool wxQTMediaBackend::Load(const wxString& fileName)
275 {
276 return Load(
277 wxURI(
278 wxString( wxT("file://") ) + fileName
279 )
280 );
281 }
282
283 bool wxQTMediaBackend::Load(const wxURI& location)
284 {
285 wxCFStringRef uri(location.BuildURI());
286
287 [m_movie release];
288 wxQTMovie* movie = [[wxQTMovie alloc] initWithURL: [NSURL URLWithString: uri.AsNSString()] error: nil ];
289
290 m_movie = movie;
291 [m_movie setBackend:this];
292 [m_movieview setMovie:movie];
293
294 return movie != nil;
295 }
296
297 void wxQTMediaBackend::FinishLoad()
298 {
299 DoShowPlayerControls(m_interfaceflags);
300
301 NSRect r =[m_movieview movieBounds];
302 m_bestSize.x = r.size.width;
303 m_bestSize.y = r.size.height;
304
305 NotifyMovieLoaded();
306
307 }
308
309 bool wxQTMediaBackend::Play()
310 {
311 [m_movieview play:nil];
312 return true;
313 }
314
315 bool wxQTMediaBackend::Pause()
316 {
317 [m_movieview pause:nil];
318 return true;
319 }
320
321 bool wxQTMediaBackend::Stop()
322 {
323 [m_movieview pause:nil];
324 [m_movieview gotoBeginning:nil];
325 return true;
326 }
327
328 double wxQTMediaBackend::GetVolume()
329 {
330 return [m_movie volume];
331 }
332
333 bool wxQTMediaBackend::SetVolume(double dVolume)
334 {
335 [m_movie setVolume:dVolume];
336 return true;
337 }
338 double wxQTMediaBackend::GetPlaybackRate()
339 {
340 return [m_movie rate];
341 }
342
343 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
344 {
345 [m_movie setRate:dRate];
346 return true;
347 }
348
349 bool wxQTMediaBackend::SetPosition(wxLongLong where)
350 {
351 QTTime position;
352 position = [m_movie currentTime];
353 position.timeValue = (where.GetValue() / 1000.0) * position.timeScale;
354 [m_movie setCurrentTime:position];
355 return true;
356 }
357
358 wxLongLong wxQTMediaBackend::GetPosition()
359 {
360 QTTime position = [m_movie currentTime];
361 return ((double) position.timeValue) / position.timeScale * 1000;
362 }
363
364 wxLongLong wxQTMediaBackend::GetDuration()
365 {
366 QTTime duration = [m_movie duration];
367 return ((double) duration.timeValue) / duration.timeScale * 1000;
368 }
369
370 wxMediaState wxQTMediaBackend::GetState()
371 {
372 if ( [m_movie isPlaying] )
373 return wxMEDIASTATE_PLAYING;
374 else
375 {
376 if ( GetPosition() == 0 )
377 return wxMEDIASTATE_STOPPED;
378 else
379 return wxMEDIASTATE_PAUSED;
380 }
381 }
382
383 void wxQTMediaBackend::Cleanup()
384 {
385 [m_movieview setMovie:NULL];
386 [m_movie release];
387 m_movie = nil;
388 }
389
390 wxSize wxQTMediaBackend::GetVideoSize() const
391 {
392 return m_bestSize;
393 }
394
395 void wxQTMediaBackend::Move(int x, int y, int w, int h)
396 {
397 }
398
399 bool wxQTMediaBackend::ShowPlayerControls(wxMediaCtrlPlayerControls flags)
400 {
401 if ( m_interfaceflags != flags )
402 DoShowPlayerControls(flags);
403
404 m_interfaceflags = flags;
405 return true;
406 }
407
408 void wxQTMediaBackend::DoShowPlayerControls(wxMediaCtrlPlayerControls flags)
409 {
410 if (flags == wxMEDIACTRLPLAYERCONTROLS_NONE )
411 {
412 [m_movieview setControllerVisible:NO];
413 }
414 else
415 {
416 [m_movieview setStepButtonsVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_STEP) ? YES:NO];
417 [m_movieview setVolumeButtonVisible:(flags & wxMEDIACTRLPLAYERCONTROLS_VOLUME) ? YES:NO];
418 }
419 }
420
421 //in source file that contains stuff you don't directly use
422 #include "wx/html/forcelnk.h"
423 FORCE_LINK_ME(basewxmediabackends);
424
425 #endif //wxUSE_MEDIACTRL