]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/mediactrl.cpp
Warning fixes.
[wxWidgets.git] / src / mac / carbon / mediactrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mac/carbon/moviectrl.cpp
3 // Purpose: wxMediaCtrl MAC CARBON QT
4 // Author: Ryan Norton <wxprojects@comcast.net>
5 // Modified by:
6 // Created: 11/07/04
7 // RCS-ID: $Id$
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 //#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 //#pragma implementation "moviectrl.h"
14 //#endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #include "wx/defs.h"
24
25 #if wxUSE_MEDIACTRL
26
27 #include "wx/mac/carbon/mediactrl.h"
28
29 #include "wx/timer.h"
30
31 IMPLEMENT_CLASS(wxMediaCtrl, wxControl);
32 IMPLEMENT_DYNAMIC_CLASS(wxMediaEvent, wxEvent);
33 DEFINE_EVENT_TYPE(wxEVT_MEDIA_FINISHED);
34
35 //uma is for wxMacFSSpec
36 #ifdef __WXMAC__
37 #include "wx/mac/uma.h"
38 #include <Movies.h>
39 #include <Gestalt.h>
40 #else
41 //quicktime media layer for mac emulation on pc
42 #include <qtml.h>
43 #endif
44
45 #include <QuickTimeComponents.h>
46
47 #ifdef __WXMAC__
48 #define MSWMOVIECHECK
49 #else
50 #define MSWMOVIECHECK if(!m_bLoaded) return 0;
51 #endif
52
53 //Time between timer calls
54 #define MOVIE_DELAY 50
55
56 // ------------------------------------------------------------------
57 // wxQTTimer - Handle Asyncronous Playing
58 // ------------------------------------------------------------------
59 class _wxQTTimer : public wxTimer
60 {
61 public:
62 _wxQTTimer(Movie movie, wxMediaCtrl* parent) :
63 m_movie(movie), m_bPaused(false), m_parent(parent)
64 {
65 }
66
67 ~_wxQTTimer()
68 {
69 }
70
71 bool GetPaused() {return m_bPaused;}
72 void SetPaused(bool bPaused) {m_bPaused = bPaused;}
73
74 void Notify()
75 {
76 if (!m_bPaused)
77 {
78 if(!IsMovieDone(m_movie))
79 MoviesTask(m_movie, MOVIE_DELAY); //Give QT time to play movie
80 else
81 {
82 Stop();
83 m_parent->Stop();
84 wxASSERT(::GetMoviesError() == noErr);
85 wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED, m_parent->GetId());
86 m_parent->GetParent()->ProcessEvent(theEvent);
87 }
88 }
89 }
90
91 protected:
92 Movie m_movie;
93 bool m_bPaused;
94 wxMediaCtrl* m_parent;
95 };
96
97 //Determines whether version 6 of QT is installed
98 Boolean _wxIsQuickTime4Installed (void)
99 {
100 #ifdef __WXMAC__
101 short error;
102 long result;
103
104 error = Gestalt (gestaltQuickTime, &result);
105 return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0400);
106 #else
107 return true;
108 #endif
109 }
110
111 bool wxMediaCtrl::InitQT ()
112 {
113 if (_wxIsQuickTime4Installed())
114 {
115 #ifndef __WXMAC__
116 int nError;
117 //-2093 no dll
118 if ((nError = InitializeQTML(0)) != noErr)
119 {
120 wxFAIL_MSG(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError));
121 }
122 #endif
123 EnterMovies();
124 return true;
125 }
126 else
127 {
128 wxFAIL_MSG(wxT("Quicktime is not installed, or Your Version of Quicktime is <= 4."));
129 return false;
130 }
131 }
132
133 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxString& fileName,
134 const wxPoint& pos, const wxSize& size,
135 long style, long WXUNUSED(driver), const wxString& name)
136 {
137 if(!DoCreate(parent, id, pos, size, style, name))
138 return false;
139
140 if(!fileName.empty())
141 {
142 if (!Load(fileName))
143 return false;
144
145 if(!Play())
146 return false;
147 }
148
149 return true;
150 }
151
152 bool wxMediaCtrl::Create(wxWindow* parent, wxWindowID id, const wxURI& location,
153 const wxPoint& pos, const wxSize& size,
154 long style, long WXUNUSED(driver), const wxString& name)
155 {
156 if(!DoCreate(parent, id, pos, size, style, name))
157 return false;
158
159 if(!location.IsReference())
160 {
161 if (!Load(location))
162 return false;
163
164 if(!Play())
165 return false;
166 }
167
168 return true;
169 }
170
171 bool wxMediaCtrl::DoCreate(wxWindow* parent, wxWindowID id,
172 const wxPoint& pos, const wxSize& size,
173 long style, const wxString& name)
174 {
175 //do some window stuff
176 if ( !wxControl::Create(parent, id, pos, size,
177 #ifdef __WXMAC__
178 MacRemoveBordersFromStyle(style),
179 #else
180 style | wxNO_BORDER,
181 #endif
182 wxDefaultValidator, name) )
183 return false;
184
185 //Set our background color to black by default
186 SetBackgroundColour(*wxBLACK);
187
188 return true;
189 }
190
191 bool wxMediaCtrl::Load(const wxString& fileName)
192 {
193 if(m_bLoaded)
194 Cleanup();
195
196 if ( !InitQT() )
197 return false;
198
199 OSErr err = noErr;
200 short movieResFile;
201 FSSpec sfFile;
202 #ifdef __WXMAC__
203 wxMacFilename2FSSpec( fileName , &sfFile ) ;
204 #else
205 if (NativePathNameToFSSpec ((char*) fileName.mb_str(), &sfFile, 0) != noErr)
206 return false;
207 #endif
208 if (OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
209 return false;
210
211 short movieResID = 0;
212 Str255 movieName;
213
214 err = NewMovieFromFile (
215 &m_movie,
216 movieResFile,
217 &movieResID,
218 movieName,
219 newMovieActive,
220 NULL); //wasChanged
221
222 CloseMovieFile (movieResFile);
223
224 if (err != noErr)
225 return false;
226
227 FinishLoad();
228
229 return m_bLoaded;
230 }
231
232 bool wxMediaCtrl::Load(const wxURI& location)
233 {
234 if(m_bLoaded)
235 Cleanup();
236
237 if ( !InitQT() )
238 return false;
239
240 wxString theURI = location.BuildURI();
241
242 OSErr err = noErr;
243
244 Handle theHandle = NewHandleClear(theURI.length() + 1);
245 wxASSERT(theHandle);
246
247 BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1);
248
249 //create the movie from the handle that refers to the URI
250 err = NewMovieFromDataRef(&m_movie, newMovieActive,
251 NULL, theHandle,
252 URLDataHandlerSubType);
253
254 DisposeHandle(theHandle);
255
256 if (err != noErr)
257 return false;
258
259 //preroll movie for streaming
260 //TODO:Async this?
261 TimeValue timeNow;
262 Fixed playRate;
263 timeNow = GetMovieTime(m_movie, NULL);
264 playRate = GetMoviePreferredRate(m_movie);
265 PrePrerollMovie(m_movie, timeNow, playRate, NULL, NULL);
266 PrerollMovie(m_movie, timeNow, playRate);
267 SetMovieRate(m_movie, playRate);
268
269 FinishLoad();
270
271 return m_bLoaded;
272 }
273
274 void wxMediaCtrl::FinishLoad()
275 {
276 m_timer = new _wxQTTimer(m_movie, (wxMediaCtrl*) this);
277 wxASSERT(m_timer);
278
279 //get the real size of the movie
280 Rect outRect;
281 ::GetMovieNaturalBoundsRect (m_movie, &outRect);
282 wxASSERT(::GetMoviesError() == noErr);
283
284 m_bestSize.x = outRect.right - outRect.left;
285 m_bestSize.y = outRect.bottom - outRect.top;
286
287 //reparent movie
288 if(GetMovieIndTrackType(m_movie, 1, VisualMediaCharacteristic/*AudioMediaCharacteristic*/, movieTrackCharacteristic | movieTrackEnabledOnly) != NULL)
289 {
290
291 #ifdef __WXMSW__
292 CreatePortAssociation(this->GetHWND(), NULL, 0L);
293 #endif
294 SetMovieGWorld(m_movie, (CGrafPtr)
295
296 #ifdef __WXMSW__
297 GetNativeWindowPort(this->GetHWND())
298 #else
299 GetWindowPort((WindowRef)this->MacGetTopLevelWindowRef())
300 #endif
301 , nil);
302 }
303
304 // wxPrintf(wxT("%u\n"), ::GetMovieTimeScale(m_movie));
305 //we want millisecond precision
306 ::SetMovieTimeScale(m_movie, 1000);
307
308 m_bLoaded = (::GetMoviesError() == noErr);
309
310 //work around refresh issues
311 wxSize size = GetParent()->GetSize();
312 GetParent()->SetSize(wxSize(size.x+1, size.y+1));
313 GetParent()->Refresh();
314 GetParent()->Update();
315 GetParent()->SetSize(size);
316 GetParent()->Refresh();
317 GetParent()->Update();
318 }
319
320 bool wxMediaCtrl::Play()
321 {
322 MSWMOVIECHECK
323 ::StartMovie(m_movie);
324 m_timer->SetPaused(false);
325 m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
326 return ::GetMoviesError() == noErr;
327 }
328
329 bool wxMediaCtrl::Pause()
330 {
331 MSWMOVIECHECK
332 ::StopMovie(m_movie);
333 m_timer->SetPaused(true);
334 m_timer->Stop();
335 return ::GetMoviesError() == noErr;
336 }
337
338 bool wxMediaCtrl::Stop()
339 {
340 MSWMOVIECHECK
341 m_timer->SetPaused(false);
342 m_timer->Stop();
343
344 ::StopMovie(m_movie);
345 if(::GetMoviesError() != noErr)
346 return false;
347
348 ::GoToBeginningOfMovie(m_movie);
349 return ::GetMoviesError() == noErr;
350 }
351
352 double wxMediaCtrl::GetPlaybackRate()
353 {
354 MSWMOVIECHECK
355 return ( ((double)::GetMovieRate(m_movie)) / 0x10000);
356 }
357
358 bool wxMediaCtrl::SetPlaybackRate(double dRate)
359 {
360 MSWMOVIECHECK
361 ::SetMovieRate(m_movie, (Fixed) (dRate * 0x10000));
362 return ::GetMoviesError() == noErr;
363 }
364
365 bool wxMediaCtrl::SetPosition(long where)
366 {
367 MSWMOVIECHECK
368 TimeRecord theTimeRecord;
369 memset(&theTimeRecord, 0, sizeof(TimeRecord));
370 theTimeRecord.value.lo = where;
371 theTimeRecord.scale = ::GetMovieTimeScale(m_movie);
372 theTimeRecord.base = ::GetMovieTimeBase(m_movie);
373 ::SetMovieTime(m_movie, &theTimeRecord);
374
375 if (::GetMoviesError() != noErr)
376 return false;
377
378 return true;
379 }
380
381 long wxMediaCtrl::GetPosition()
382 {
383 MSWMOVIECHECK
384 return ::GetMovieTime(m_movie, NULL);
385 }
386
387 long wxMediaCtrl::GetDuration()
388 {
389 MSWMOVIECHECK
390 return ::GetMovieDuration(m_movie);
391 }
392
393 wxMediaState wxMediaCtrl::GetState()
394 {
395 if ( !m_bLoaded || (m_timer->IsRunning() == false && m_timer->GetPaused() == false) )
396 return wxMEDIASTATE_STOPPED;
397
398 if( m_timer->IsRunning() == true )
399 return wxMEDIASTATE_PLAYING;
400 else
401 return wxMEDIASTATE_PAUSED;
402 }
403
404 void wxMediaCtrl::Cleanup()
405 {
406 delete m_timer;
407 m_timer = NULL;
408
409 StopMovie(m_movie);
410 DisposeMovie(m_movie);
411
412 //Note that ExitMovies() is not neccessary, but
413 //the docs are fuzzy on whether or not TerminateQTML is
414 ExitMovies();
415
416 #ifndef __WXMAC__
417 TerminateQTML();
418 #endif
419 }
420
421 wxMediaCtrl::~wxMediaCtrl()
422 {
423 if(m_bLoaded)
424 Cleanup();
425 }
426
427 wxSize wxMediaCtrl::DoGetBestSize() const
428 {
429 return m_bestSize;
430 }
431
432 void wxMediaCtrl::DoMoveWindow(int x, int y, int w, int h)
433 {
434 wxControl::DoMoveWindow(x,y,w,h);
435
436 if(m_bLoaded)
437 {
438 #ifdef __WXMAC__
439 Rect theRect = {y, x, y+h, x+w};
440 #else
441 Rect theRect = {0, 0, h, w};
442 #endif
443 ::SetMovieBox(m_movie, &theRect);
444 wxASSERT(::GetMoviesError() == noErr);
445 }
446 }
447
448 #endif //wxUSE_MOVIECTRL