]> git.saurik.com Git - wxWidgets.git/blob - src/cocoa/mediactrl.mm
fix double->unsigned char warnings
[wxWidgets.git] / src / cocoa / mediactrl.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mac/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$
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 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "mediactrl.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 //---------------------------------------------------------------------------
32 // Includes
33 //---------------------------------------------------------------------------
34 #include "wx/mediactrl.h"
35
36 //---------------------------------------------------------------------------
37 // Compilation guard
38 //---------------------------------------------------------------------------
39 #if wxUSE_MEDIACTRL
40
41 //===========================================================================
42 // BACKEND DECLARATIONS
43 //===========================================================================
44
45 //---------------------------------------------------------------------------
46 //
47 // wxQTMediaBackend
48 //
49 //---------------------------------------------------------------------------
50
51 //---------------------------------------------------------------------------
52 // QT Includes
53 //---------------------------------------------------------------------------
54 #include "wx/timer.h"
55 #include <QuickTime/QuickTime.h>
56
57 #include "wx/cocoa/autorelease.h"
58 #include "wx/cocoa/string.h"
59
60 #import <AppKit/NSMovie.h>
61 #import <AppKit/NSMovieView.h>
62
63
64 class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend
65 {
66 public:
67
68 wxQTMediaBackend();
69 ~wxQTMediaBackend();
70
71 virtual bool CreateControl(wxControl* ctrl, wxWindow* parent,
72 wxWindowID id,
73 const wxPoint& pos,
74 const wxSize& size,
75 long style,
76 const wxValidator& validator,
77 const wxString& name);
78
79 virtual bool Play();
80 virtual bool Pause();
81 virtual bool Stop();
82
83 virtual bool Load(const wxString& fileName);
84 virtual bool Load(const wxURI& location);
85
86 virtual wxMediaState GetState();
87
88 virtual bool SetPosition(wxLongLong where);
89 virtual wxLongLong GetPosition();
90 virtual wxLongLong GetDuration();
91
92 virtual void Move(int x, int y, int w, int h);
93 wxSize GetVideoSize() const;
94
95 virtual double GetPlaybackRate();
96 virtual bool SetPlaybackRate(double dRate);
97
98 void Cleanup();
99 void FinishLoad();
100
101 wxSize m_bestSize; //Original movie size
102 Movie m_movie; //QT Movie handle/instance
103 NSMovieView* m_movieview; //NSMovieView instance
104 wxControl* m_ctrl; //Parent control
105 bool m_bVideo; //Whether or not we have video
106 class _wxQTTimer* m_timer; //Timer for streaming the movie
107
108 DECLARE_DYNAMIC_CLASS(wxQTMediaBackend);
109 };
110
111
112 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
113 //
114 // wxQTMediaBackend
115 //
116 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
117
118 IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend);
119
120 //Time between timer calls
121 #define MOVIE_DELAY 100
122
123 // --------------------------------------------------------------------------
124 // wxQTTimer - Handle Asyncronous Playing
125 // --------------------------------------------------------------------------
126 class _wxQTTimer : public wxTimer
127 {
128 public:
129 _wxQTTimer(Movie movie, wxQTMediaBackend* parent) :
130 m_movie(movie), m_bPaused(false), m_parent(parent)
131 {
132 }
133
134 ~_wxQTTimer()
135 {
136 }
137
138 bool GetPaused() {return m_bPaused;}
139 void SetPaused(bool bPaused) {m_bPaused = bPaused;}
140
141 //-----------------------------------------------------------------------
142 // _wxQTTimer::Notify
143 //
144 // 1) Checks to see if the movie is done, and if not continues
145 // streaming the movie
146 // 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of
147 // the movie.
148 //-----------------------------------------------------------------------
149 void Notify()
150 {
151 if (!m_bPaused)
152 {
153 if(!IsMovieDone(m_movie))
154 MoviesTask(m_movie, MOVIE_DELAY);
155 else
156 {
157 wxMediaEvent theEvent(wxEVT_MEDIA_STOP,
158 m_parent->m_ctrl->GetId());
159 m_parent->m_ctrl->ProcessEvent(theEvent);
160
161 if(theEvent.IsAllowed())
162 {
163 Stop();
164 m_parent->Stop();
165 wxASSERT(::GetMoviesError() == noErr);
166
167 //send the event to our child
168 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED,
169 m_parent->m_ctrl->GetId());
170 m_parent->m_ctrl->ProcessEvent(theEvent);
171 }
172 }
173 }
174 }
175
176 protected:
177 Movie m_movie; //Our movie instance
178 bool m_bPaused; //Whether we are paused or not
179 wxQTMediaBackend* m_parent; //Backend pointer
180 };
181
182 //---------------------------------------------------------------------------
183 // wxQTMediaBackend Constructor
184 //
185 // Sets m_timer to NULL signifying we havn't loaded anything yet
186 //---------------------------------------------------------------------------
187 wxQTMediaBackend::wxQTMediaBackend() : m_timer(NULL)
188 {
189 }
190
191 //---------------------------------------------------------------------------
192 // wxQTMediaBackend Destructor
193 //
194 // 1) Cleans up the QuickTime movie instance
195 // 2) Decrements the QuickTime reference counter - if this reaches
196 // 0, QuickTime shuts down
197 // 3) Decrements the QuickTime Windows Media Layer reference counter -
198 // if this reaches 0, QuickTime shuts down the Windows Media Layer
199 //---------------------------------------------------------------------------
200 wxQTMediaBackend::~wxQTMediaBackend()
201 {
202 if(m_timer)
203 Cleanup();
204
205 //Note that ExitMovies() is not neccessary...
206 ExitMovies();
207 }
208
209 //---------------------------------------------------------------------------
210 // wxQTMediaBackend::CreateControl
211 //
212 // 1) Intializes QuickTime
213 // 2) Creates the control window
214 //---------------------------------------------------------------------------
215 bool wxQTMediaBackend::CreateControl(wxControl* inctrl, wxWindow* parent,
216 wxWindowID wid,
217 const wxPoint& pos,
218 const wxSize& size,
219 long style,
220 const wxValidator& validator,
221 const wxString& name)
222 {
223 EnterMovies();
224
225 wxMediaCtrl* ctrl = (wxMediaCtrl*) inctrl;
226
227 //Create the control base
228 wxASSERT(ctrl->CreateBase(parent,wid,pos,size,style, validator, size));
229
230 //Create the NSMovieView
231 ctrl->SetNSView(NULL);
232 NSView* theView = [[NSMovieView alloc] initWithFrame: ctrl->MakeDefaultNSRect(size)];
233 ctrl->SetNSView(theView);
234 [theView release];
235
236 if (parent)
237 {
238 parent->AddChild(ctrl);
239 parent->CocoaAddChild(ctrl);
240 ctrl->SetInitialFrameRect(pos,size);
241 }
242
243 m_movieview = theView;
244 m_ctrl = ctrl;
245 return true;
246 }
247
248 //---------------------------------------------------------------------------
249 // wxQTMediaBackend::Load (file version)
250 //
251 // Calls the URI version
252 //---------------------------------------------------------------------------
253 bool wxQTMediaBackend::Load(const wxString& fileName)
254 {
255 return Load(
256 wxURI(
257 wxString( wxT("file://") ) + fileName
258 )
259 );
260 }
261
262 //---------------------------------------------------------------------------
263 // wxQTMediaBackend::Load (URL Version)
264 //
265 // 1) Build an escaped URI from location
266 // ...
267 //---------------------------------------------------------------------------
268 bool wxQTMediaBackend::Load(const wxURI& location)
269 {
270 if(m_timer)
271 Cleanup();
272
273 wxString theURI = location.BuildURI();
274
275 [m_movieview setMovie:[[NSMovie alloc] initWithURL: [NSURL URLWithString: wxNSStringWithWxString(theURI)]
276 byReference: YES ] ];
277
278 m_movie = (Movie) [[m_movieview movie] QTMovie];
279
280 //preroll movie for streaming
281 //TODO:Async this using threads?
282 TimeValue timeNow;
283 Fixed playRate;
284 timeNow = GetMovieTime(m_movie, NULL);
285 playRate = GetMoviePreferredRate(m_movie);
286 PrePrerollMovie(m_movie, timeNow, playRate, NULL, NULL);
287 PrerollMovie(m_movie, timeNow, playRate);
288 SetMovieRate(m_movie, playRate);
289
290 FinishLoad();
291
292 return ::GetMoviesError() == noErr;
293 }
294
295 //---------------------------------------------------------------------------
296 // wxQTMediaBackend::FinishLoad
297 //
298 // 1) Create the movie timer
299 // 2) Get real size of movie for GetBestSize/sizers
300 // 3) See if there is video in the movie, and if so then either
301 // SetMovieGWorld if < 10.2 or use Native CreateMovieControl
302 // 4) Set the movie time scale to something usable so that seeking
303 // etc. will work correctly
304 // 5) Refresh parent window
305 //---------------------------------------------------------------------------
306 void wxQTMediaBackend::FinishLoad()
307 {
308 m_timer = new _wxQTTimer(m_movie, (wxQTMediaBackend*) this);
309 wxASSERT(m_timer);
310
311 //get the real size of the movie
312 Rect outRect;
313 ::GetMovieNaturalBoundsRect (m_movie, &outRect);
314 wxASSERT(::GetMoviesError() == noErr);
315
316 m_bestSize.x = outRect.right - outRect.left;
317 m_bestSize.y = outRect.bottom - outRect.top;
318
319 //we want millisecond precision
320 ::SetMovieTimeScale(m_movie, 1000);
321 wxASSERT(::GetMoviesError() == noErr);
322
323 //
324 //Here, if the parent of the control has a sizer - we
325 //tell it to recalculate the size of this control since
326 //the user opened a seperate media file
327 //
328 m_ctrl->InvalidateBestSize();
329 m_ctrl->GetParent()->Layout();
330 m_ctrl->GetParent()->Refresh();
331 m_ctrl->GetParent()->Update();
332 }
333
334 //---------------------------------------------------------------------------
335 // wxQTMediaBackend::Play
336 //
337 // 1) Start the QT movie
338 // 2) Start the movie loading timer
339 //---------------------------------------------------------------------------
340 bool wxQTMediaBackend::Play()
341 {
342 ::StartMovie(m_movie);
343 m_timer->SetPaused(false);
344 m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
345 return ::GetMoviesError() == noErr;
346 }
347
348 //---------------------------------------------------------------------------
349 // wxQTMediaBackend::Pause
350 //
351 // 1) Stop the movie
352 // 2) Stop the movie timer
353 //---------------------------------------------------------------------------
354 bool wxQTMediaBackend::Pause()
355 {
356 ::StopMovie(m_movie);
357 m_timer->SetPaused(true);
358 m_timer->Stop();
359 return ::GetMoviesError() == noErr;
360 }
361
362 //---------------------------------------------------------------------------
363 // wxQTMediaBackend::Stop
364 //
365 // 1) Stop the movie
366 // 2) Stop the movie timer
367 // 3) Seek to the beginning of the movie
368 //---------------------------------------------------------------------------
369 bool wxQTMediaBackend::Stop()
370 {
371 m_timer->SetPaused(false);
372 m_timer->Stop();
373
374 ::StopMovie(m_movie);
375 if(::GetMoviesError() != noErr)
376 return false;
377
378 ::GoToBeginningOfMovie(m_movie);
379 return ::GetMoviesError() == noErr;
380 }
381
382 //---------------------------------------------------------------------------
383 // wxQTMediaBackend::GetPlaybackRate
384 //
385 // 1) Get the movie playback rate from ::GetMovieRate
386 //---------------------------------------------------------------------------
387 double wxQTMediaBackend::GetPlaybackRate()
388 {
389 return ( ((double)::GetMovieRate(m_movie)) / 0x10000);
390 }
391
392 //---------------------------------------------------------------------------
393 // wxQTMediaBackend::SetPlaybackRate
394 //
395 // 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate
396 //---------------------------------------------------------------------------
397 bool wxQTMediaBackend::SetPlaybackRate(double dRate)
398 {
399 ::SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
400 return ::GetMoviesError() == noErr;
401 }
402
403 //---------------------------------------------------------------------------
404 // wxQTMediaBackend::SetPosition
405 //
406 // 1) Create a time record struct (TimeRecord) with appropriate values
407 // 2) Pass struct to SetMovieTime
408 //---------------------------------------------------------------------------
409 bool wxQTMediaBackend::SetPosition(wxLongLong where)
410 {
411 TimeRecord theTimeRecord;
412 memset(&theTimeRecord, 0, sizeof(TimeRecord));
413 theTimeRecord.value.lo = where.GetValue();
414 theTimeRecord.scale = ::GetMovieTimeScale(m_movie);
415 theTimeRecord.base = ::GetMovieTimeBase(m_movie);
416 ::SetMovieTime(m_movie, &theTimeRecord);
417
418 if (::GetMoviesError() != noErr)
419 return false;
420
421 return true;
422 }
423
424 //---------------------------------------------------------------------------
425 // wxQTMediaBackend::GetPosition
426 //
427 // Calls GetMovieTime
428 //---------------------------------------------------------------------------
429 wxLongLong wxQTMediaBackend::GetPosition()
430 {
431 return ::GetMovieTime(m_movie, NULL);
432 }
433
434 //---------------------------------------------------------------------------
435 // wxQTMediaBackend::GetDuration
436 //
437 // Calls GetMovieDuration
438 //---------------------------------------------------------------------------
439 wxLongLong wxQTMediaBackend::GetDuration()
440 {
441 return ::GetMovieDuration(m_movie);
442 }
443
444 //---------------------------------------------------------------------------
445 // wxQTMediaBackend::GetState
446 //
447 // Determines the current state - the timer keeps track of whether or not
448 // we are paused or stopped (if the timer is running we are playing)
449 //---------------------------------------------------------------------------
450 wxMediaState wxQTMediaBackend::GetState()
451 {
452 if ( !m_timer || (m_timer->IsRunning() == false &&
453 m_timer->GetPaused() == false) )
454 return wxMEDIASTATE_STOPPED;
455
456 if( m_timer->IsRunning() == true )
457 return wxMEDIASTATE_PLAYING;
458 else
459 return wxMEDIASTATE_PAUSED;
460 }
461
462 //---------------------------------------------------------------------------
463 // wxQTMediaBackend::Cleanup
464 //
465 // Diposes of the movie timer, Control if native, and stops and disposes
466 // of the QT movie
467 //---------------------------------------------------------------------------
468 void wxQTMediaBackend::Cleanup()
469 {
470 delete m_timer;
471 m_timer = NULL;
472
473 [[m_movieview movie] release];
474 [m_movieview setMovie:NULL];
475 }
476
477 //---------------------------------------------------------------------------
478 // wxQTMediaBackend::GetVideoSize
479 //
480 // Returns the actual size of the QT movie
481 //---------------------------------------------------------------------------
482 wxSize wxQTMediaBackend::GetVideoSize() const
483 {
484 return m_bestSize;
485 }
486
487 //---------------------------------------------------------------------------
488 // wxQTMediaBackend::Move
489 //
490 // Nothin... cocoa takes care of this for us
491 //---------------------------------------------------------------------------
492 void wxQTMediaBackend::Move(int x, int y, int w, int h)
493 {
494 }
495
496
497 //in source file that contains stuff you don't directly use
498 #include <wx/html/forcelnk.h>
499 FORCE_LINK_ME(basewxmediabackends);
500
501 #endif //wxUSE_MEDIACTRL
502
503
504
505
506