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