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