]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/moviectrl.cpp
allow multiple movie loading as per Julian's suggestion. DOC.
[wxWidgets.git] / src / mac / carbon / moviectrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mac/carbon/moviectrl.cpp
3 // Purpose: wxMovieCtrl 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 #define wxUSE_MOVIECTRL 1
24
25 #if wxUSE_MOVIECTRL
26
27 #include "wx/moviectrl.h"
28 #include "wx/sound.h"
29 #include "wx/timer.h"
30
31 IMPLEMENT_CLASS(wxMovieCtrl, wxControl);
32 IMPLEMENT_DYNAMIC_CLASS(wxMovieEvent, wxEvent);
33 DEFINE_EVENT_TYPE(wxEVT_MOVIE_FINISHED);
34
35 //MESSY headers
36 #ifdef __WXMAC__
37 #include "wx/mac/uma.h"
38 #include <Movies.h>
39 #include <Gestalt.h>
40 #endif
41
42 //quicktime media layer only required for mac emulation on pc
43 #ifndef __WXMAC__
44 #include <qtml.h>
45 #endif
46
47 #include <QuickTimeComponents.h>
48
49 //Time between timer calls
50 #define MOVIE_DELAY 100
51
52 // ------------------------------------------------------------------
53 // wxQTTimer - Handle Asyncronous Playing
54 // ------------------------------------------------------------------
55 class _wxQTTimer : public wxTimer
56 {
57 public:
58 _wxQTTimer(Movie movie, wxMovieCtrl* parent) :
59 m_movie(movie), m_bPaused(false), m_parent(parent)
60 {
61 }
62
63 ~_wxQTTimer()
64 {
65 }
66
67 bool GetPaused() {return m_bPaused;}
68 void SetPaused(bool bPaused) {m_bPaused = bPaused;}
69
70 void Notify()
71 {
72 if (!m_bPaused)
73 {
74 if(!IsMovieDone(m_movie))
75 MoviesTask(m_movie, MOVIE_DELAY); //Give QT time to play movie
76 else
77 {
78 Stop();
79 ::GoToBeginningOfMovie(m_movie);
80 wxASSERT( ::GetMoviesError() == noErr );
81 wxMovieEvent theEvent(wxEVT_MOVIE_FINISHED, m_parent->GetId());
82 m_parent->GetParent()->ProcessEvent(theEvent);
83 }
84 }
85 }
86
87 protected:
88 Movie m_movie;
89 bool m_bPaused;
90 wxMovieCtrl* m_parent;
91 };
92
93 //Determines whether version 3 of QT is installed
94 Boolean wxIsQuickTime3Installed (void)
95 {
96 #ifdef __WXMAC__
97 short error;
98 long result;
99
100 error = Gestalt (gestaltQuickTime, &result);
101 return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0300);
102 #else
103 return true;
104 #endif
105 }
106
107 bool wxMovieCtrl::InitQT ()
108 {
109 if (wxIsQuickTime3Installed())
110 {
111 #ifndef __WXMAC__
112 int nError;
113 //-2093 no dll
114 if ((nError = InitializeQTML(0)) != noErr)
115 {
116 wxFAIL_MSG(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError));
117 }
118 #endif
119 EnterMovies();
120 return true;
121 }
122 else
123 {
124 wxFAIL_MSG(wxT("Quicktime is not installed, or Your Version of Quicktime is <= 4."));
125 return false;
126 }
127 }
128
129 bool wxMovieCtrl::Create(wxWindow* parent, wxWindowID id, const wxString& fileName,
130 const wxString& label, const wxPoint& pos, const wxSize& size,
131 long WXUNUSED(style), const wxString& name)
132 {
133 //do some window stuff
134 if ( !wxControl::Create(parent, id, pos, size, wxNO_BORDER, wxDefaultValidator, name) )
135 return false;
136
137 //Set our background color to black by default
138 SetBackgroundColour(*wxBLACK);
139
140 if(!fileName.empty())
141 {
142 if (!Load(fileName))
143 return false;
144
145 SetLabel(label);
146
147 if(!Play())
148 return false;
149 }
150 else
151 wxControl::SetLabel(label);
152
153 return true;
154 }
155
156 bool wxMovieCtrl::Load(const wxString& fileName)
157 {
158 if(m_bLoaded)
159 Cleanup();
160
161 if ( !InitQT() )
162 return false;
163
164 OSErr err = noErr;
165 short movieResFile;
166 FSSpec sfFile;
167 #ifdef __WXMAC__
168 wxMacFilename2FSSpec( m_sndname , &sfFile ) ;
169 #else
170 int nError;
171 if ((nError = NativePathNameToFSSpec ((char*) fileName.c_str(), &sfFile, 0)) != noErr)
172 {
173 wxFAIL_MSG(wxString::Format(wxT("File:%s does not exist\nError:%i"),
174 fileName.c_str(), nError));
175 return false;
176 }
177 #endif
178 if (OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
179 {
180 wxFAIL_MSG(wxT("Quicktime couldn't open the file"));
181 return false;
182 }
183 short movieResID = 0;
184 Str255 movieName;
185
186 err = NewMovieFromFile (
187 &m_movie,
188 movieResFile,
189 &movieResID,
190 movieName,
191 newMovieActive,
192 NULL); //wasChanged
193
194 CloseMovieFile (movieResFile);
195
196 if (err != noErr)
197 {
198 wxFAIL_MSG(wxT("Could not create movie"));
199 return false;
200 }
201
202 m_timer = new _wxQTTimer(m_movie, (wxMovieCtrl*) this);
203 wxASSERT(m_timer);
204
205 //get the real size of the movie
206 Rect outRect;
207 ::GetMovieNaturalBoundsRect (m_movie, &outRect);
208
209 m_bestSize.x = outRect.right - outRect.left;
210 m_bestSize.y = outRect.bottom - outRect.top;
211
212 //soldier in OnSize
213 this->Connect( wxID_ANY,
214 wxEVT_SIZE,
215 (wxObjectEventFunction) (wxEventFunction) (wxSizeEventFunction) &wxMovieCtrl::OnSize );
216
217 //reparent movie
218 #ifdef __WXMSW__
219 CreatePortAssociation(this->GetHWND(), NULL, 0L);
220 #endif
221 SetMovieGWorld(m_movie, (CGrafPtr)
222
223 #ifdef __WXMSW__
224 GetNativeWindowPort(this->GetHWND())
225 #else
226 this->GetHandle()
227 #endif
228 , nil);
229
230 return true;
231 }
232
233
234 bool wxMovieCtrl::Play()
235 {
236 ::StartMovie(m_movie);
237 m_timer->SetPaused(false);
238 m_timer->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
239 return ::GetMoviesError() == noErr;
240 }
241
242 bool wxMovieCtrl::Pause()
243 {
244 ::StopMovie(m_movie);
245 m_timer->SetPaused(true);
246 return ::GetMoviesError() == noErr;
247 }
248
249 bool wxMovieCtrl::Stop()
250 {
251 m_timer->SetPaused(false);
252
253 ::StopMovie(m_movie);
254 if(::GetMoviesError() != noErr)
255 return false;
256
257 ::GoToBeginningOfMovie(m_movie);
258 return ::GetMoviesError() == noErr;
259 }
260
261 double wxMovieCtrl::GetPlaybackRate()
262 {
263 return (double) (::GetMovieTimeScale(m_movie) / 0x10000f);
264 }
265
266 bool wxMovieCtrl::SetPlaybackRate(double dRate)
267 {
268 ::SetMovieTimeScale(m_movie, (Fixed) (dRate * 0x10000));
269 return ::GetMoviesError() == noErr;
270 }
271
272 #if wxUSE_DATETIME
273
274 bool wxMovieCtrl::Seek(const wxTimeSpan& where)
275 {
276 TimeRecord theTimeRecord;
277 theTimeRecord.value.lo = ((size_t)where.GetMilliseconds().ToLong()) * 10;
278 theTimeRecord.scale = ::GetMovieTimeScale(m_movie);
279 theTimeRecord.base = ::GetMovieTimeBase(m_movie);
280 ::SetMovieTime(m_movie, &theTimeRecord);
281
282 if (::GetMoviesError() != noErr)
283 return false;
284
285 return true;
286 }
287
288 wxTimeSpan wxMovieCtrl::Tell()
289 {
290 return (wxTimeSpan) ::GetMovieTime(m_movie, NULL);
291 }
292
293 wxTimeSpan wxMovieCtrl::Length()
294 {
295 return (wxTimeSpan) ::GetMovieDuration(m_movie);
296 }
297
298 #endif // wxUSE_DATETIME
299
300 wxMovieCtrlState wxMovieCtrl::GetState()
301 {
302 if( m_timer->IsRunning() == true )
303 return wxMOVIECTRL_STOPPED;
304
305 if ( m_timer->GetPaused() == false )
306 return wxMOVIECTRL_PLAYING;
307 else
308 return wxMOVIECTRL_PAUSED;
309 }
310
311 void wxMovieCtrl::Cleanup()
312 {
313 //soldier in OnSize
314 this->Disconnect( wxID_ANY,
315 wxEVT_SIZE,
316 (wxObjectEventFunction) (wxEventFunction) (wxSizeEventFunction) &wxMovieCtrl::OnSize );
317
318 delete m_timer;
319
320 StopMovie(m_movie);
321 DisposeMovie(m_movie);
322
323 //Note that ExitMovies() is not neccessary, but
324 //the docs are fuzzy on whether or not TerminateQTML is
325 ExitMovies();
326
327 #ifndef __WXMAC__
328 TerminateQTML();
329 #endif
330 }
331
332 wxMovieCtrl::~wxMovieCtrl()
333 {
334 if(m_bLoaded)
335 Cleanup();
336 }
337
338 wxSize wxMovieCtrl::DoGetBestSize() const
339 {
340 return m_bestSize;
341 }
342
343 void wxMovieCtrl::OnSize(wxSizeEvent& evt)
344 {
345 Rect theRect;
346 theRect.left = 0;
347 theRect.top = 0;
348 theRect.bottom = evt.GetSize().y;
349 theRect.right = evt.GetSize().x;
350
351 ::SetMovieBox(m_movie, &theRect);
352
353 wxASSERT(::GetMoviesError() == noErr);
354 evt.Skip();
355 }
356
357 #endif //wxUSE_MOVIECTRL