]>
Commit | Line | Data |
---|---|---|
1a680109 | 1 | ///////////////////////////////////////////////////////////////////////////// |
ff4aedc5 RN |
2 | // Name: mac/carbon/mediactrl.cpp |
3 | // Purpose: Built-in Media Backends for Mac | |
1a680109 | 4 | // Author: Ryan Norton <wxprojects@comcast.net> |
ff4aedc5 | 5 | // Modified by: |
1a680109 RN |
6 | // Created: 11/07/04 |
7 | // RCS-ID: $Id$ | |
3b5023b9 | 8 | // Copyright: (c) 2004-2005 Ryan Norton, portions (c) 2004 Kevin Olliver |
1a680109 RN |
9 | // Licence: wxWindows licence |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
ff4aedc5 RN |
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 | |
1a680109 RN |
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 | ||
ff4aedc5 RN |
31 | //--------------------------------------------------------------------------- |
32 | // Includes | |
33 | //--------------------------------------------------------------------------- | |
34 | #include "wx/mediactrl.h" | |
1a680109 | 35 | |
ff4aedc5 RN |
36 | //--------------------------------------------------------------------------- |
37 | // Compilation guard | |
38 | //--------------------------------------------------------------------------- | |
1a680109 RN |
39 | #if wxUSE_MEDIACTRL |
40 | ||
3b5023b9 RN |
41 | //--------------------------------------------------------------------------- |
42 | // Whether or not to use OSX 10.2's CreateMovieControl for native QuickTime | |
43 | // control - i.e. native positioning and event handling etc.. | |
44 | //--------------------------------------------------------------------------- | |
45 | #ifndef wxUSE_CREATEMOVIECONTROL | |
d0ee33f5 WS |
46 | # if defined( __WXMAC_OSX__ ) && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_2 ) |
47 | # define wxUSE_CREATEMOVIECONTROL 1 | |
48 | # else | |
49 | # define wxUSE_CREATEMOVIECONTROL 0 | |
50 | # endif | |
3b5023b9 RN |
51 | #endif |
52 | ||
ff4aedc5 RN |
53 | //=========================================================================== |
54 | // BACKEND DECLARATIONS | |
55 | //=========================================================================== | |
212945de | 56 | |
ff4aedc5 RN |
57 | //--------------------------------------------------------------------------- |
58 | // | |
59 | // wxQTMediaBackend | |
60 | // | |
61 | //--------------------------------------------------------------------------- | |
1a680109 | 62 | |
ff4aedc5 RN |
63 | //--------------------------------------------------------------------------- |
64 | // QT Includes | |
65 | //--------------------------------------------------------------------------- | |
1a680109 | 66 | //uma is for wxMacFSSpec |
1a680109 | 67 | #include "wx/mac/uma.h" |
ff4aedc5 | 68 | #include "wx/timer.h" |
768c6e8b | 69 | #ifndef __DARWIN__ |
1a680109 RN |
70 | #include <Movies.h> |
71 | #include <Gestalt.h> | |
ff4aedc5 | 72 | #include <QuickTimeComponents.h> //Standard QT stuff |
768c6e8b SC |
73 | #else |
74 | #include <QuickTime/QuickTimeComponents.h> | |
75 | #endif | |
1a680109 | 76 | |
3b5023b9 | 77 | //Determines whether version 4 of QT is installed (Pretty much for classic only) |
ff4aedc5 RN |
78 | Boolean _wxIsQuickTime4Installed (void) |
79 | { | |
80 | short error; | |
81 | long result; | |
1a680109 | 82 | |
ff4aedc5 RN |
83 | error = Gestalt (gestaltQuickTime, &result); |
84 | return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0400); | |
85 | } | |
86 | ||
ff2b312f | 87 | class WXDLLIMPEXP_MEDIA wxQTMediaBackend : public wxMediaBackend |
ff4aedc5 RN |
88 | { |
89 | public: | |
90 | ||
91 | wxQTMediaBackend(); | |
92 | ~wxQTMediaBackend(); | |
93 | ||
d0ee33f5 | 94 | virtual bool CreateControl(wxControl* ctrl, wxWindow* parent, |
ff4aedc5 | 95 | wxWindowID id, |
d0ee33f5 | 96 | const wxPoint& pos, |
ff4aedc5 | 97 | const wxSize& size, |
d0ee33f5 | 98 | long style, |
ff4aedc5 RN |
99 | const wxValidator& validator, |
100 | const wxString& name); | |
101 | ||
102 | virtual bool Play(); | |
103 | virtual bool Pause(); | |
104 | virtual bool Stop(); | |
105 | ||
106 | virtual bool Load(const wxString& fileName); | |
107 | virtual bool Load(const wxURI& location); | |
108 | ||
109 | virtual wxMediaState GetState(); | |
110 | ||
111 | virtual bool SetPosition(wxLongLong where); | |
112 | virtual wxLongLong GetPosition(); | |
113 | virtual wxLongLong GetDuration(); | |
114 | ||
115 | virtual void Move(int x, int y, int w, int h); | |
116 | wxSize GetVideoSize() const; | |
117 | ||
118 | virtual double GetPlaybackRate(); | |
119 | virtual bool SetPlaybackRate(double dRate); | |
120 | ||
c5191fbd VZ |
121 | virtual double GetVolume(); |
122 | virtual bool SetVolume(double); | |
123 | ||
ff4aedc5 RN |
124 | void Cleanup(); |
125 | void FinishLoad(); | |
126 | ||
127 | wxSize m_bestSize; //Original movie size | |
20b69855 | 128 | #ifdef __WXMAC_OSX__ |
ff4aedc5 | 129 | struct MovieType** m_movie; //QT Movie handle/instance |
20b69855 SC |
130 | #else |
131 | Movie m_movie ; | |
132 | #endif | |
ff4aedc5 RN |
133 | wxControl* m_ctrl; //Parent control |
134 | bool m_bVideo; //Whether or not we have video | |
135 | class _wxQTTimer* m_timer; //Timer for streaming the movie | |
136 | ||
d0ee33f5 | 137 | DECLARE_DYNAMIC_CLASS(wxQTMediaBackend) |
ff4aedc5 RN |
138 | }; |
139 | ||
140 | ||
141 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
142 | // | |
143 | // wxQTMediaBackend | |
d0ee33f5 | 144 | // |
ff4aedc5 RN |
145 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
146 | ||
147 | IMPLEMENT_DYNAMIC_CLASS(wxQTMediaBackend, wxMediaBackend); | |
1a680109 RN |
148 | |
149 | //Time between timer calls | |
ff4aedc5 | 150 | #define MOVIE_DELAY 100 |
1a680109 | 151 | |
ff4aedc5 | 152 | // -------------------------------------------------------------------------- |
1a680109 | 153 | // wxQTTimer - Handle Asyncronous Playing |
ff4aedc5 | 154 | // -------------------------------------------------------------------------- |
1a680109 RN |
155 | class _wxQTTimer : public wxTimer |
156 | { | |
157 | public: | |
ff4aedc5 | 158 | _wxQTTimer(Movie movie, wxQTMediaBackend* parent) : |
1a680109 RN |
159 | m_movie(movie), m_bPaused(false), m_parent(parent) |
160 | { | |
161 | } | |
162 | ||
163 | ~_wxQTTimer() | |
164 | { | |
165 | } | |
166 | ||
167 | bool GetPaused() {return m_bPaused;} | |
168 | void SetPaused(bool bPaused) {m_bPaused = bPaused;} | |
169 | ||
ff4aedc5 RN |
170 | //----------------------------------------------------------------------- |
171 | // _wxQTTimer::Notify | |
172 | // | |
173 | // 1) Checks to see if the movie is done, and if not continues | |
174 | // streaming the movie | |
175 | // 2) Sends the wxEVT_MEDIA_STOP event if we have reached the end of | |
176 | // the movie. | |
177 | //----------------------------------------------------------------------- | |
1a680109 RN |
178 | void Notify() |
179 | { | |
180 | if (!m_bPaused) | |
181 | { | |
182 | if(!IsMovieDone(m_movie)) | |
d0ee33f5 | 183 | MoviesTask(m_movie, MOVIE_DELAY); |
1a680109 RN |
184 | else |
185 | { | |
d0ee33f5 | 186 | wxMediaEvent theEvent(wxEVT_MEDIA_STOP, |
ff4aedc5 RN |
187 | m_parent->m_ctrl->GetId()); |
188 | m_parent->m_ctrl->ProcessEvent(theEvent); | |
189 | ||
190 | if(theEvent.IsAllowed()) | |
191 | { | |
192 | Stop(); | |
193 | m_parent->Stop(); | |
194 | wxASSERT(::GetMoviesError() == noErr); | |
195 | ||
196 | //send the event to our child | |
d0ee33f5 | 197 | wxMediaEvent theEvent(wxEVT_MEDIA_FINISHED, |
ff4aedc5 RN |
198 | m_parent->m_ctrl->GetId()); |
199 | m_parent->m_ctrl->ProcessEvent(theEvent); | |
200 | } | |
1a680109 RN |
201 | } |
202 | } | |
203 | } | |
204 | ||
205 | protected: | |
ff4aedc5 RN |
206 | Movie m_movie; //Our movie instance |
207 | bool m_bPaused; //Whether we are paused or not | |
208 | wxQTMediaBackend* m_parent; //Backend pointer | |
1a680109 RN |
209 | }; |
210 | ||
ff4aedc5 | 211 | //--------------------------------------------------------------------------- |
e7b97da3 | 212 | // wxQTMediaBackend Constructor |
ff4aedc5 RN |
213 | // |
214 | // Sets m_timer to NULL signifying we havn't loaded anything yet | |
215 | //--------------------------------------------------------------------------- | |
216 | wxQTMediaBackend::wxQTMediaBackend() : m_timer(NULL) | |
1a680109 | 217 | { |
1a680109 RN |
218 | } |
219 | ||
ff4aedc5 RN |
220 | //--------------------------------------------------------------------------- |
221 | // wxQTMediaBackend Destructor | |
222 | // | |
223 | // 1) Cleans up the QuickTime movie instance | |
224 | // 2) Decrements the QuickTime reference counter - if this reaches | |
225 | // 0, QuickTime shuts down | |
226 | // 3) Decrements the QuickTime Windows Media Layer reference counter - | |
227 | // if this reaches 0, QuickTime shuts down the Windows Media Layer | |
228 | //--------------------------------------------------------------------------- | |
229 | wxQTMediaBackend::~wxQTMediaBackend() | |
1a680109 | 230 | { |
ff4aedc5 RN |
231 | if(m_timer) |
232 | Cleanup(); | |
1a680109 | 233 | |
3103e8a9 | 234 | //Note that ExitMovies() is not necessary... |
ff4aedc5 | 235 | ExitMovies(); |
1a680109 RN |
236 | } |
237 | ||
ff4aedc5 RN |
238 | //--------------------------------------------------------------------------- |
239 | // wxQTMediaBackend::CreateControl | |
240 | // | |
241 | // 1) Intializes QuickTime | |
242 | // 2) Creates the control window | |
243 | //--------------------------------------------------------------------------- | |
d0ee33f5 | 244 | bool wxQTMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent, |
ff4aedc5 | 245 | wxWindowID id, |
d0ee33f5 | 246 | const wxPoint& pos, |
ff4aedc5 | 247 | const wxSize& size, |
d0ee33f5 | 248 | long style, |
ff4aedc5 RN |
249 | const wxValidator& validator, |
250 | const wxString& name) | |
1a680109 | 251 | { |
3b5023b9 | 252 | //Don't bother in Native control mode |
d0ee33f5 | 253 | #if defined( __WXMAC__ ) && TARGET_API_MAC_OSX && ( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_2 ) |
ff4aedc5 | 254 | if (!_wxIsQuickTime4Installed()) |
1a680109 | 255 | return false; |
3b5023b9 | 256 | #endif |
1a680109 | 257 | |
ff4aedc5 RN |
258 | EnterMovies(); |
259 | ||
260 | // | |
261 | // Create window | |
262 | // By default wxWindow(s) is created with a border - | |
263 | // so we need to get rid of those | |
264 | // | |
265 | // Since we don't have a child window like most other | |
266 | // backends, we don't need wxCLIP_CHILDREN | |
267 | // | |
3b5023b9 | 268 | if ( ! |
d0ee33f5 WS |
269 | |
270 | #if wxUSE_CREATEMOVIECONTROL | |
3dee36ae WS |
271 | ctrl->wxWindow::Create(parent, id, pos, size, |
272 | wxWindow::MacRemoveBordersFromStyle(style), | |
273 | name) | |
ecd20d4a | 274 | #else |
3dee36ae WS |
275 | ctrl->wxControl::Create(parent, id, pos, size, |
276 | wxWindow::MacRemoveBordersFromStyle(style), | |
277 | validator, name) | |
d0ee33f5 | 278 | #endif |
3b5023b9 | 279 | ) |
1a680109 RN |
280 | return false; |
281 | ||
ecd20d4a | 282 | #if wxUSE_VALIDATORS |
3dee36ae | 283 | ctrl->SetValidator(validator); |
ecd20d4a RN |
284 | #endif |
285 | ||
ff4aedc5 | 286 | m_ctrl = ctrl; |
1a680109 RN |
287 | return true; |
288 | } | |
289 | ||
ff4aedc5 RN |
290 | //--------------------------------------------------------------------------- |
291 | // wxQTMediaBackend::Load (file version) | |
292 | // | |
293 | // 1) Get an FSSpec from the Windows path name | |
294 | // 2) Open the movie | |
295 | // 3) Obtain the movie instance from the movie resource | |
3b5023b9 RN |
296 | // 4) Close the movie resource |
297 | // 5) Finish loading | |
ff4aedc5 RN |
298 | //--------------------------------------------------------------------------- |
299 | bool wxQTMediaBackend::Load(const wxString& fileName) | |
1a680109 | 300 | { |
ff4aedc5 | 301 | if(m_timer) |
1a680109 RN |
302 | Cleanup(); |
303 | ||
1a680109 RN |
304 | OSErr err = noErr; |
305 | short movieResFile; | |
306 | FSSpec sfFile; | |
d0ee33f5 WS |
307 | |
308 | //FIXME:wxMacFilename2FSSpec crashes on empty string - | |
099c3b27 RN |
309 | //does it crash on other strings too and should this |
310 | //"fix" be put in the carbon wxSound? | |
311 | if (fileName.empty()) | |
312 | return false; | |
d0ee33f5 | 313 | |
ff4aedc5 | 314 | wxMacFilename2FSSpec( fileName , &sfFile ); |
d0ee33f5 | 315 | |
1a680109 RN |
316 | if (OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr) |
317 | return false; | |
318 | ||
319 | short movieResID = 0; | |
320 | Str255 movieName; | |
321 | ||
322 | err = NewMovieFromFile ( | |
323 | &m_movie, | |
324 | movieResFile, | |
325 | &movieResID, | |
326 | movieName, | |
327 | newMovieActive, | |
328 | NULL); //wasChanged | |
329 | ||
330 | CloseMovieFile (movieResFile); | |
331 | ||
332 | if (err != noErr) | |
333 | return false; | |
334 | ||
335 | FinishLoad(); | |
336 | ||
ff4aedc5 | 337 | return ::GetMoviesError() == noErr; |
1a680109 RN |
338 | } |
339 | ||
ff4aedc5 | 340 | //--------------------------------------------------------------------------- |
3b5023b9 | 341 | // wxQTMediaBackend::Load (URL Version) |
ff4aedc5 | 342 | // |
3b5023b9 RN |
343 | // 1) Build an escaped URI from location |
344 | // 2) Create a handle to store the URI string | |
345 | // 3) Put the URI string inside the handle | |
346 | // 4) Make a QuickTime URL data ref from the handle with the URI in it | |
347 | // 5) Clean up the URI string handle | |
348 | // 6) Do some prerolling | |
349 | // 7) Finish Loading | |
ff4aedc5 RN |
350 | //--------------------------------------------------------------------------- |
351 | bool wxQTMediaBackend::Load(const wxURI& location) | |
1a680109 | 352 | { |
ff4aedc5 | 353 | if(m_timer) |
1a680109 RN |
354 | Cleanup(); |
355 | ||
1a680109 RN |
356 | wxString theURI = location.BuildURI(); |
357 | ||
358 | OSErr err = noErr; | |
359 | ||
360 | Handle theHandle = NewHandleClear(theURI.length() + 1); | |
361 | wxASSERT(theHandle); | |
362 | ||
363 | BlockMove(theURI.mb_str(), *theHandle, theURI.length() + 1); | |
364 | ||
365 | //create the movie from the handle that refers to the URI | |
d0ee33f5 WS |
366 | err = NewMovieFromDataRef(&m_movie, newMovieActive, |
367 | NULL, theHandle, | |
1a680109 RN |
368 | URLDataHandlerSubType); |
369 | ||
370 | DisposeHandle(theHandle); | |
371 | ||
372 | if (err != noErr) | |
373 | return false; | |
374 | ||
375 | //preroll movie for streaming | |
3b5023b9 | 376 | //TODO:Async this using threads? |
1a680109 RN |
377 | TimeValue timeNow; |
378 | Fixed playRate; | |
379 | timeNow = GetMovieTime(m_movie, NULL); | |
380 | playRate = GetMoviePreferredRate(m_movie); | |
381 | PrePrerollMovie(m_movie, timeNow, playRate, NULL, NULL); | |
382 | PrerollMovie(m_movie, timeNow, playRate); | |
383 | SetMovieRate(m_movie, playRate); | |
384 | ||
385 | FinishLoad(); | |
386 | ||
ff4aedc5 | 387 | return ::GetMoviesError() == noErr; |
1a680109 RN |
388 | } |
389 | ||
ff4aedc5 | 390 | //--------------------------------------------------------------------------- |
e7b97da3 | 391 | // wxQTMediaBackend::FinishLoad |
ff4aedc5 | 392 | // |
3b5023b9 RN |
393 | // 1) Create the movie timer |
394 | // 2) Get real size of movie for GetBestSize/sizers | |
395 | // 3) See if there is video in the movie, and if so then either | |
396 | // SetMovieGWorld if < 10.2 or use Native CreateMovieControl | |
397 | // 4) Set the movie time scale to something usable so that seeking | |
398 | // etc. will work correctly | |
399 | // 5) Refresh parent window | |
ff4aedc5 RN |
400 | //--------------------------------------------------------------------------- |
401 | void wxQTMediaBackend::FinishLoad() | |
1a680109 | 402 | { |
ff4aedc5 | 403 | m_timer = new _wxQTTimer(m_movie, (wxQTMediaBackend*) this); |
1a680109 RN |
404 | wxASSERT(m_timer); |
405 | ||
406 | //get the real size of the movie | |
407 | Rect outRect; | |
408 | ::GetMovieNaturalBoundsRect (m_movie, &outRect); | |
409 | wxASSERT(::GetMoviesError() == noErr); | |
410 | ||
411 | m_bestSize.x = outRect.right - outRect.left; | |
412 | m_bestSize.y = outRect.bottom - outRect.top; | |
3b5023b9 | 413 | |
ff4aedc5 | 414 | //reparent movie/*AudioMediaCharacteristic*/ |
d0ee33f5 WS |
415 | if(GetMovieIndTrackType(m_movie, 1, |
416 | VisualMediaCharacteristic, | |
417 | movieTrackCharacteristic | | |
ff4aedc5 | 418 | movieTrackEnabledOnly) != NULL) |
d0ee33f5 WS |
419 | { |
420 | #if wxUSE_CREATEMOVIECONTROL | |
3dee36ae WS |
421 | // |
422 | //Native CreateMovieControl QT control (Thanks to Kevin Olliver's | |
423 | //wxQTMovie for some of this). | |
424 | // | |
425 | #define GetControlPeer(whatever) ctrl->m_peer | |
426 | wxMediaCtrl* ctrl = (wxMediaCtrl*) m_ctrl; | |
427 | Rect bounds = wxMacGetBoundsForControl(m_ctrl, | |
428 | m_ctrl->GetPosition(), | |
429 | m_ctrl->GetSize()); | |
430 | ||
431 | //Dispose of old control for new one | |
432 | if (GetControlPeer(m_ctrl) && GetControlPeer(m_ctrl)->Ok() ) | |
433 | GetControlPeer(m_ctrl)->Dispose(); | |
434 | ||
435 | //Options- | |
436 | //kMovieControlOptionXXX | |
437 | //HideController - hide the movie controller | |
438 | //LocateTopLeft - movie is pinned to top left rather than centered in the control | |
439 | //EnableEditing - Allows programmatic editing and dragn'drop | |
440 | //HandleEditingHI- Installs event stuff for edit menu - forces EnableEditing also | |
441 | //SetKeysEnabled - Allows keyboard input | |
442 | //ManuallyIdled - app handles movie idling rather than internal timer event loop | |
d0ee33f5 | 443 | ::CreateMovieControl( |
3b5023b9 | 444 | (WindowRef) |
d0ee33f5 WS |
445 | ctrl->MacGetTopLevelWindowRef(), //parent |
446 | &bounds, //control bounds | |
447 | m_movie, //movie handle | |
448 | kMovieControlOptionHideController | |
449 | | kMovieControlOptionLocateTopLeft | |
450 | | kMovieControlOptionSetKeysEnabled | |
3b5023b9 | 451 | // | kMovieControlOptionManuallyIdled |
d0ee33f5 | 452 | , //flags |
ecd20d4a | 453 | ctrl->m_peer->GetControlRefAddr() ); |
d0ee33f5 | 454 | |
ecd20d4a | 455 | ::EmbedControl(ctrl->m_peer->GetControlRef(), (ControlRef)ctrl->GetParent()->GetHandle()); |
3b5023b9 | 456 | #else |
3dee36ae WS |
457 | // |
458 | //"Emulation" | |
459 | // | |
d0ee33f5 WS |
460 | SetMovieGWorld(m_movie, |
461 | (CGrafPtr) | |
ff4aedc5 RN |
462 | GetWindowPort( |
463 | (WindowRef) | |
464 | m_ctrl->MacGetTopLevelWindowRef() | |
d0ee33f5 | 465 | ), |
ff4aedc5 | 466 | nil); |
3b5023b9 | 467 | #endif |
1a680109 RN |
468 | } |
469 | ||
1a680109 RN |
470 | //we want millisecond precision |
471 | ::SetMovieTimeScale(m_movie, 1000); | |
ff4aedc5 RN |
472 | wxASSERT(::GetMoviesError() == noErr); |
473 | ||
474 | // | |
475 | //Here, if the parent of the control has a sizer - we | |
476 | //tell it to recalculate the size of this control since | |
3103e8a9 | 477 | //the user opened a separate media file |
ff4aedc5 RN |
478 | // |
479 | m_ctrl->InvalidateBestSize(); | |
480 | m_ctrl->GetParent()->Layout(); | |
481 | m_ctrl->GetParent()->Refresh(); | |
482 | m_ctrl->GetParent()->Update(); | |
c5191fbd VZ |
483 | |
484 | //send loaded event | |
485 | wxMediaEvent theEvent(wxEVT_MEDIA_LOADED, | |
486 | m_ctrl->GetId()); | |
487 | m_ctrl->AddPendingEvent(theEvent); | |
1a680109 RN |
488 | } |
489 | ||
ff4aedc5 | 490 | //--------------------------------------------------------------------------- |
e7b97da3 | 491 | // wxQTMediaBackend::Play |
ff4aedc5 | 492 | // |
3b5023b9 RN |
493 | // 1) Start the QT movie |
494 | // 2) Start the movie loading timer | |
ff4aedc5 RN |
495 | //--------------------------------------------------------------------------- |
496 | bool wxQTMediaBackend::Play() | |
1a680109 | 497 | { |
1a680109 RN |
498 | ::StartMovie(m_movie); |
499 | m_timer->SetPaused(false); | |
500 | m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS); | |
501 | return ::GetMoviesError() == noErr; | |
502 | } | |
503 | ||
ff4aedc5 | 504 | //--------------------------------------------------------------------------- |
e7b97da3 | 505 | // wxQTMediaBackend::Pause |
ff4aedc5 | 506 | // |
3b5023b9 RN |
507 | // 1) Stop the movie |
508 | // 2) Stop the movie timer | |
ff4aedc5 RN |
509 | //--------------------------------------------------------------------------- |
510 | bool wxQTMediaBackend::Pause() | |
1a680109 | 511 | { |
1a680109 RN |
512 | ::StopMovie(m_movie); |
513 | m_timer->SetPaused(true); | |
514 | m_timer->Stop(); | |
515 | return ::GetMoviesError() == noErr; | |
516 | } | |
517 | ||
ff4aedc5 | 518 | //--------------------------------------------------------------------------- |
e7b97da3 | 519 | // wxQTMediaBackend::Stop |
ff4aedc5 | 520 | // |
3b5023b9 RN |
521 | // 1) Stop the movie |
522 | // 2) Stop the movie timer | |
523 | // 3) Seek to the beginning of the movie | |
ff4aedc5 RN |
524 | //--------------------------------------------------------------------------- |
525 | bool wxQTMediaBackend::Stop() | |
1a680109 | 526 | { |
1a680109 RN |
527 | m_timer->SetPaused(false); |
528 | m_timer->Stop(); | |
529 | ||
530 | ::StopMovie(m_movie); | |
531 | if(::GetMoviesError() != noErr) | |
532 | return false; | |
d0ee33f5 | 533 | |
1a680109 RN |
534 | ::GoToBeginningOfMovie(m_movie); |
535 | return ::GetMoviesError() == noErr; | |
536 | } | |
537 | ||
ff4aedc5 | 538 | //--------------------------------------------------------------------------- |
e7b97da3 | 539 | // wxQTMediaBackend::GetPlaybackRate |
ff4aedc5 | 540 | // |
3b5023b9 | 541 | // 1) Get the movie playback rate from ::GetMovieRate |
ff4aedc5 RN |
542 | //--------------------------------------------------------------------------- |
543 | double wxQTMediaBackend::GetPlaybackRate() | |
1a680109 | 544 | { |
1a680109 RN |
545 | return ( ((double)::GetMovieRate(m_movie)) / 0x10000); |
546 | } | |
547 | ||
ff4aedc5 | 548 | //--------------------------------------------------------------------------- |
e7b97da3 | 549 | // wxQTMediaBackend::SetPlaybackRate |
ff4aedc5 | 550 | // |
3b5023b9 | 551 | // 1) Convert dRate to Fixed and Set the movie rate through SetMovieRate |
ff4aedc5 RN |
552 | //--------------------------------------------------------------------------- |
553 | bool wxQTMediaBackend::SetPlaybackRate(double dRate) | |
1a680109 | 554 | { |
1a680109 RN |
555 | ::SetMovieRate(m_movie, (Fixed) (dRate * 0x10000)); |
556 | return ::GetMoviesError() == noErr; | |
557 | } | |
558 | ||
ff4aedc5 | 559 | //--------------------------------------------------------------------------- |
e7b97da3 | 560 | // wxQTMediaBackend::SetPosition |
ff4aedc5 | 561 | // |
3b5023b9 RN |
562 | // 1) Create a time record struct (TimeRecord) with appropriate values |
563 | // 2) Pass struct to SetMovieTime | |
ff4aedc5 RN |
564 | //--------------------------------------------------------------------------- |
565 | bool wxQTMediaBackend::SetPosition(wxLongLong where) | |
1a680109 | 566 | { |
1a680109 RN |
567 | TimeRecord theTimeRecord; |
568 | memset(&theTimeRecord, 0, sizeof(TimeRecord)); | |
ff4aedc5 | 569 | theTimeRecord.value.lo = where.GetValue(); |
1a680109 RN |
570 | theTimeRecord.scale = ::GetMovieTimeScale(m_movie); |
571 | theTimeRecord.base = ::GetMovieTimeBase(m_movie); | |
572 | ::SetMovieTime(m_movie, &theTimeRecord); | |
573 | ||
574 | if (::GetMoviesError() != noErr) | |
575 | return false; | |
576 | ||
577 | return true; | |
578 | } | |
579 | ||
ff4aedc5 | 580 | //--------------------------------------------------------------------------- |
e7b97da3 | 581 | // wxQTMediaBackend::GetPosition |
ff4aedc5 | 582 | // |
3b5023b9 | 583 | // Calls GetMovieTime |
ff4aedc5 RN |
584 | //--------------------------------------------------------------------------- |
585 | wxLongLong wxQTMediaBackend::GetPosition() | |
1a680109 | 586 | { |
1a680109 RN |
587 | return ::GetMovieTime(m_movie, NULL); |
588 | } | |
589 | ||
ff4aedc5 | 590 | //--------------------------------------------------------------------------- |
c5191fbd VZ |
591 | // wxQTMediaBackend::GetVolume |
592 | // | |
593 | // Gets the volume through GetMovieVolume - which returns a 16 bit short - | |
594 | // | |
595 | // +--------+--------+ | |
596 | // + (1) + (2) + | |
597 | // +--------+--------+ | |
598 | // | |
599 | // (1) first 8 bits are value before decimal | |
600 | // (2) second 8 bits are value after decimal | |
601 | // | |
602 | // Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to | |
603 | // 1 (full gain and sound) | |
604 | //--------------------------------------------------------------------------- | |
605 | double wxQTMediaBackend::GetVolume() | |
606 | { | |
607 | short sVolume = GetMovieVolume(m_movie); | |
608 | ||
609 | if(sVolume & (128 << 8)) //negative - no sound | |
610 | return 0.0; | |
611 | ||
612 | return (sVolume & (127 << 8)) ? 1.0 : ((double)(sVolume & 255)) / 255.0; | |
613 | } | |
614 | ||
615 | //--------------------------------------------------------------------------- | |
616 | // wxQTMediaBackend::SetVolume | |
617 | // | |
618 | // Sets the volume through SetMovieVolume - which takes a 16 bit short - | |
619 | // | |
620 | // +--------+--------+ | |
621 | // + (1) + (2) + | |
622 | // +--------+--------+ | |
623 | // | |
624 | // (1) first 8 bits are value before decimal | |
625 | // (2) second 8 bits are value after decimal | |
626 | // | |
627 | // Volume ranges from -1.0 (gain but no sound), 0 (no sound and no gain) to | |
628 | // 1 (full gain and sound) | |
629 | //--------------------------------------------------------------------------- | |
630 | bool wxQTMediaBackend::SetVolume(double dVolume) | |
631 | { | |
632 | short sVolume = (short) (dVolume >= .9999 ? 1 << 8 : (dVolume * 255) ); | |
633 | SetMovieVolume(m_movie, sVolume); | |
634 | return true; | |
635 | } | |
636 | ||
637 | //--------------------------------------------------------------------------- | |
e7b97da3 | 638 | // wxQTMediaBackend::GetDuration |
ff4aedc5 | 639 | // |
3b5023b9 | 640 | // Calls GetMovieDuration |
ff4aedc5 RN |
641 | //--------------------------------------------------------------------------- |
642 | wxLongLong wxQTMediaBackend::GetDuration() | |
1a680109 | 643 | { |
1a680109 RN |
644 | return ::GetMovieDuration(m_movie); |
645 | } | |
646 | ||
ff4aedc5 | 647 | //--------------------------------------------------------------------------- |
e7b97da3 | 648 | // wxQTMediaBackend::GetState |
ff4aedc5 | 649 | // |
3b5023b9 RN |
650 | // Determines the current state - the timer keeps track of whether or not |
651 | // we are paused or stopped (if the timer is running we are playing) | |
ff4aedc5 RN |
652 | //--------------------------------------------------------------------------- |
653 | wxMediaState wxQTMediaBackend::GetState() | |
1a680109 | 654 | { |
d0ee33f5 | 655 | if ( !m_timer || (m_timer->IsRunning() == false && |
ff4aedc5 | 656 | m_timer->GetPaused() == false) ) |
1a680109 RN |
657 | return wxMEDIASTATE_STOPPED; |
658 | ||
d0ee33f5 | 659 | if( m_timer->IsRunning() ) |
1a680109 RN |
660 | return wxMEDIASTATE_PLAYING; |
661 | else | |
662 | return wxMEDIASTATE_PAUSED; | |
663 | } | |
664 | ||
ff4aedc5 | 665 | //--------------------------------------------------------------------------- |
e7b97da3 | 666 | // wxQTMediaBackend::Cleanup |
ff4aedc5 | 667 | // |
3b5023b9 RN |
668 | // Diposes of the movie timer, Control if native, and stops and disposes |
669 | // of the QT movie | |
ff4aedc5 RN |
670 | //--------------------------------------------------------------------------- |
671 | void wxQTMediaBackend::Cleanup() | |
1a680109 RN |
672 | { |
673 | delete m_timer; | |
674 | m_timer = NULL; | |
d0ee33f5 WS |
675 | |
676 | #if wxUSE_CREATEMOVIECONTROL | |
ecd20d4a | 677 | DisposeControl(((wxMediaCtrl*)m_ctrl)->m_peer->GetControlRef()); |
3b5023b9 | 678 | #endif |
1a680109 RN |
679 | |
680 | StopMovie(m_movie); | |
681 | DisposeMovie(m_movie); | |
1a680109 RN |
682 | } |
683 | ||
ff4aedc5 | 684 | //--------------------------------------------------------------------------- |
e7b97da3 | 685 | // wxQTMediaBackend::GetVideoSize |
ff4aedc5 | 686 | // |
3b5023b9 | 687 | // Returns the actual size of the QT movie |
ff4aedc5 RN |
688 | //--------------------------------------------------------------------------- |
689 | wxSize wxQTMediaBackend::GetVideoSize() const | |
1a680109 RN |
690 | { |
691 | return m_bestSize; | |
692 | } | |
693 | ||
ff4aedc5 RN |
694 | //--------------------------------------------------------------------------- |
695 | // wxQTMediaBackend::Move | |
696 | // | |
d0ee33f5 | 697 | // We need to do this even when using native qt control because |
4b60077b | 698 | // CreateMovieControl is broken in this regard... |
ff4aedc5 RN |
699 | //--------------------------------------------------------------------------- |
700 | void wxQTMediaBackend::Move(int x, int y, int w, int h) | |
1a680109 | 701 | { |
d0ee33f5 | 702 | #if !wxUSE_CREATEMOVIECONTROL |
ff4aedc5 | 703 | if(m_timer) |
1a680109 | 704 | { |
e7b97da3 RD |
705 | if ( m_ctrl ) |
706 | { | |
707 | m_ctrl->GetParent()->MacWindowToRootWindow(&x, &y); | |
708 | } | |
d0ee33f5 | 709 | |
1a680109 | 710 | Rect theRect = {y, x, y+h, x+w}; |
ff4aedc5 | 711 | |
1a680109 RN |
712 | ::SetMovieBox(m_movie, &theRect); |
713 | wxASSERT(::GetMoviesError() == noErr); | |
714 | } | |
4b60077b RN |
715 | #else |
716 | if(m_timer && m_ctrl) | |
717 | { | |
718 | m_ctrl->GetParent()->MacWindowToRootWindow(&x, &y); | |
719 | ||
720 | ::MoveControl( (ControlRef) m_ctrl->GetHandle(), x, y ); | |
721 | m_ctrl->GetParent()->Refresh(); | |
722 | m_ctrl->GetParent()->Update(); | |
723 | } | |
3b5023b9 | 724 | #endif |
1a680109 RN |
725 | } |
726 | ||
ff4aedc5 RN |
727 | |
728 | //in source file that contains stuff you don't directly use | |
f572d649 | 729 | #include "wx/html/forcelnk.h" |
ff4aedc5 RN |
730 | FORCE_LINK_ME(basewxmediabackends); |
731 | ||
732 | #endif //wxUSE_MEDIACTRL |