]>
Commit | Line | Data |
---|---|---|
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 | ||
58 | #import <AppKit/NSMovie.h> | |
59 | #import <AppKit/NSMovieView.h> | |
60 | ||
c560088c | 61 | class WXDLLIMPEXP_FWD_MEDIA wxQTMediaBackend; |
38e4bfde | 62 | |
c560088c SC |
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 | |
38e4bfde SC |
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 | |
c560088c | 117 | wxQTMovie* m_movie; //QTMovie handle/instance |
38e4bfde | 118 | QTMovieView* m_movieview; //QTMovieView instance |
38e4bfde SC |
119 | |
120 | wxMediaCtrlPlayerControls m_interfaceflags; // Saved interface flags | |
121 | ||
122 | DECLARE_DYNAMIC_CLASS(wxQTMediaBackend); | |
123 | }; | |
124 | ||
c560088c SC |
125 | // -------------------------------------------------------------------------- |
126 | // wxQTMovie | |
127 | // -------------------------------------------------------------------------- | |
38e4bfde | 128 | |
c560088c | 129 | @implementation wxQTMovie |
38e4bfde | 130 | |
c560088c SC |
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 | } | |
38e4bfde | 150 | |
c560088c SC |
151 | -(void)dealloc |
152 | { | |
153 | NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; | |
154 | [nc removeObserver:self]; | |
155 | ||
156 | [super dealloc]; | |
157 | } | |
38e4bfde | 158 | |
c560088c | 159 | -(wxQTMediaBackend*) backend; |
38e4bfde | 160 | { |
c560088c SC |
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 ) | |
38e4bfde | 172 | { |
c560088c SC |
173 | if ( m_backend->SendStopEvent() ) |
174 | m_backend->QueueFinishEvent(); | |
38e4bfde | 175 | } |
c560088c | 176 | } |
38e4bfde | 177 | |
c560088c SC |
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 ) | |
38e4bfde | 189 | { |
c560088c | 190 | m_backend->QueuePlayEvent(); |
38e4bfde | 191 | } |
c560088c | 192 | } |
38e4bfde | 193 | |
c560088c SC |
194 | -(void)loadStateChanged:(QTMovie *)movie |
195 | { | |
196 | long loadState = [[movie attributeForKey:QTMovieLoadStateAttribute] longValue]; | |
197 | if (loadState >= QTMovieLoadStatePlayable) | |
38e4bfde | 198 | { |
c560088c SC |
199 | // the movie has loaded enough media data to begin playing |
200 | } | |
201 | else if (loadState >= QTMovieLoadStateLoaded) | |
202 | { | |
203 | m_backend->FinishLoad(); | |
38e4bfde | 204 | } |
c560088c SC |
205 | else if (loadState == -1) |
206 | { | |
207 | // error occurred | |
208 | } | |
209 | } | |
38e4bfde | 210 | |
c560088c SC |
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); | |
38e4bfde | 228 | |
38e4bfde SC |
229 | wxQTMediaBackend::wxQTMediaBackend() : |
230 | m_interfaceflags(wxMEDIACTRLPLAYERCONTROLS_NONE), | |
c560088c | 231 | m_movie(nil), m_movieview(nil) |
38e4bfde SC |
232 | { |
233 | } | |
234 | ||
38e4bfde SC |
235 | wxQTMediaBackend::~wxQTMediaBackend() |
236 | { | |
c560088c | 237 | Cleanup(); |
38e4bfde SC |
238 | } |
239 | ||
38e4bfde SC |
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 | ||
c560088c SC |
250 | mediactrl->DontCreatePeer(); |
251 | ||
38e4bfde SC |
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 | { | |
c560088c | 285 | wxCFStringRef uri(location.BuildURI()); |
38e4bfde SC |
286 | |
287 | [m_movie release]; | |
c560088c | 288 | wxQTMovie* movie = [[wxQTMovie alloc] initWithURL: [NSURL URLWithString: uri.AsNSString()] error: nil ]; |
38e4bfde | 289 | |
c560088c SC |
290 | m_movie = movie; |
291 | [m_movie setBackend:this]; | |
38e4bfde SC |
292 | [m_movieview setMovie:movie]; |
293 | ||
38e4bfde SC |
294 | return movie != nil; |
295 | } | |
296 | ||
297 | void wxQTMediaBackend::FinishLoad() | |
298 | { | |
c560088c SC |
299 | DoShowPlayerControls(m_interfaceflags); |
300 | ||
38e4bfde SC |
301 | NSRect r =[m_movieview movieBounds]; |
302 | m_bestSize.x = r.size.width; | |
303 | m_bestSize.y = r.size.height; | |
c560088c SC |
304 | |
305 | NotifyMovieLoaded(); | |
38e4bfde | 306 | |
38e4bfde SC |
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 | { | |
c560088c | 372 | if ( [m_movie isPlaying] ) |
38e4bfde SC |
373 | return wxMEDIASTATE_PLAYING; |
374 | else | |
c560088c SC |
375 | { |
376 | if ( GetPosition() == 0 ) | |
377 | return wxMEDIASTATE_STOPPED; | |
378 | else | |
379 | return wxMEDIASTATE_PAUSED; | |
380 | } | |
38e4bfde SC |
381 | } |
382 | ||
383 | void wxQTMediaBackend::Cleanup() | |
384 | { | |
38e4bfde | 385 | [m_movieview setMovie:NULL]; |
c560088c SC |
386 | [m_movie release]; |
387 | m_movie = nil; | |
38e4bfde SC |
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 |