]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/sound.cpp
Removed unused event table entries
[wxWidgets.git] / src / mac / carbon / sound.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: sound.cpp
3 // Purpose: wxSound class implementation: optional
4 // Author: Ryan Norton, Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Ryan Norton, Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "sound.h"
14 #endif
15
16 #include "wx/object.h"
17 #include "wx/string.h"
18 #include "wx/log.h"
19 #include "wx/file.h"
20 #include "wx/sound.h"
21 #include "wx/timer.h"
22
23 #if wxUSE_SOUND
24
25 // Carbon QT Implementation Details -
26 //
27 // Memory:
28 // 1) OpenDefaultComponent(MovieImportType, kQTFileTypeWave);
29 // 2) NewMovie(0);
30 // 3) MovieImportDataRef() //Pass Memory Location to this
31 // 4) PlayMovie();
32 // 5) IsMovieDone(), MoviesTask() //2nd param is minimum wait time to allocate to quicktime
33 //
34 // File:
35 // 1) Obtain FSSpec
36 // 2) Call OpenMovieFile
37 // 3) Call NewMovieFromFile
38 // 4) Call CloseMovieFile
39 // 4) PlayMovie();
40 // 5) IsMovieDone(), MoviesTask() //2nd param is minimum wait time to allocate to quicktime
41 //
42
43 #ifdef __WXMAC__
44 #include "wx/mac/private.h"
45 #include <Movies.h>
46 #include <Gestalt.h>
47 #endif
48
49 #if defined __WXMAC__ && defined __DARWIN__/*TARGET_CARBON*/
50 #ifdef __APPLE_CC__
51 #include <Carbon/Carbon.h>
52 #else
53 #include <Carbon.h>
54 #endif
55 #else
56 #include <Sound.h>
57 #endif
58
59 //quicktime media layer only required for mac emulation on pc
60 #ifndef __WXMAC__
61 #include <qtml.h>
62 #endif
63
64 #include <QuickTimeComponents.h>
65
66 //Time inbetween timer calls
67 #define MOVIE_DELAY 100
68
69 // ------------------------------------------------------------------
70 // wxQTTimer - Handle Asyncronous Playing
71 // ------------------------------------------------------------------
72 class wxQTTimer : public wxTimer
73 {
74 public:
75 wxQTTimer(Movie movie, bool bLoop) :
76 m_movie(movie), m_bLoop(bLoop)
77 {
78 }
79
80 ~wxQTTimer()
81 {
82 Shutdown();
83 }
84
85 void Shutdown()
86 {
87 StopMovie(m_movie);
88 DisposeMovie(m_movie);
89 m_movie = NULL ;
90 Stop();
91
92 //Note that ExitMovies() is not neccessary, but
93 //the docs are fuzzy on whether or not TerminateQTML is
94 ExitMovies();
95
96 #ifndef __WXMAC__
97 TerminateQTML();
98 #endif
99 }
100
101 void Notify()
102 {
103 if(IsMovieDone(m_movie))
104 {
105 if (!m_bLoop)
106 Shutdown();
107 else
108 {
109 StopMovie(m_movie);
110 GoToBeginningOfMovie(m_movie);
111 StartMovie(m_movie);
112 }
113 }
114 else
115 MoviesTask(m_movie, MOVIE_DELAY); //Give QT time to play movie
116 }
117
118
119 Movie& GetMovie() {return m_movie;}
120 protected:
121 Movie m_movie;
122 bool m_bLoop;
123 };
124
125
126 class wxSMTimer : public wxTimer
127 {
128 public:
129 wxSMTimer(void* hSnd, void* pSndChannel, const bool& bLoop)
130 : m_hSnd(hSnd), m_pSndChannel(pSndChannel), m_bLoop(bLoop)
131 {
132 }
133
134 ~wxSMTimer()
135 {
136 Shutdown();
137 }
138
139 void Notify()
140 {
141 SCStatus stat;
142
143 if (SndChannelStatus((SndChannelPtr)m_pSndChannel, sizeof(SCStatus), &stat) != 0)
144 Shutdown();
145
146 //if the sound isn't playing anymore, see if it's looped,
147 //and if so play it again, otherwise close things up
148 if (stat.scChannelBusy == FALSE)
149 {
150 if (m_bLoop)
151 {
152 if(SndPlay((SndChannelPtr)m_pSndChannel, (SndListHandle) m_hSnd, true) != noErr)
153 Shutdown();
154 }
155 else
156 Shutdown();
157 }
158 }
159
160 void Shutdown()
161 {
162 SndDisposeChannel((SndChannelPtr)m_pSndChannel, TRUE);
163 Stop();
164 }
165
166 protected:
167 void* m_hSnd;
168 void* m_pSndChannel;
169 bool m_bLoop;
170 };
171
172 // ------------------------------------------------------------------
173 // wxSound
174 // ------------------------------------------------------------------
175
176 //Determines whether version 4 of QT is installed
177 Boolean wxIsQuickTime4Installed (void)
178 {
179 #ifdef __WXMAC__
180 short error;
181 long result;
182
183 error = Gestalt (gestaltQuickTime, &result);
184 return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0400);
185 #else
186 return true;
187 #endif
188 }
189
190 inline bool wxInitQT ()
191 {
192 if (wxIsQuickTime4Installed())
193 {
194 #ifndef __WXMAC__
195 int nError;
196 //-2093 no dll
197 if ((nError = InitializeQTML(0)) != noErr)
198 wxLogSysError(wxString::Format("Couldn't Initialize Quicktime-%i", nError));
199 #endif
200 EnterMovies();
201 return true;
202 }
203 else
204 {
205 wxLogSysError("Quicktime is not installed, or Your Version of Quicktime is <= 4.");
206 return false;
207 }
208 }
209
210 wxSound::wxSound()
211 : m_hSnd(NULL), m_waveLength(0), m_pTimer(NULL), m_type(wxSound_NONE)
212 {
213 }
214
215 wxSound::wxSound(const wxString& sFileName, bool isResource)
216 : m_hSnd(NULL), m_waveLength(0), m_pTimer(NULL), m_type(wxSound_NONE)
217 {
218 Create(sFileName, isResource);
219 }
220
221 wxSound::wxSound(int size, const wxByte* data)
222 : m_hSnd((char*)data), m_waveLength(size), m_pTimer(NULL), m_type(wxSound_MEMORY)
223 {
224 if (!wxInitQT())
225 m_type = wxSound_NONE;
226 }
227
228 wxSound::~wxSound()
229 {
230 }
231
232 bool wxSound::Create(const wxString& fileName, bool isResource)
233 {
234 if(!wxInitQT())
235 return false;
236
237 FreeData();
238
239 if (isResource)
240 {
241 #ifdef __WXMAC__
242 m_type = wxSound_RESOURCE;
243
244 Str255 lpSnd ;
245
246 wxMacStringToPascal( fileName , lpSnd ) ;
247
248 m_sndname = lpSnd;
249 m_hSnd = (char*) GetNamedResource('snd ', (const unsigned char *) lpSnd);
250 #else
251 return false;
252 #endif
253 }
254 else
255 {
256 m_type = wxSound_FILE;
257 m_sndname = fileName;
258 }
259
260 return true;
261 }
262
263 bool wxSound::DoPlay(unsigned flags) const
264 {
265 // wxASSERT(m_pTimer == NULL || !((wxTimer*)m_pTimer)->IsRunning() );
266 FreeData();
267
268 Movie movie;
269
270 switch(m_type)
271 {
272 case wxSound_MEMORY:
273 {
274 Handle myHandle, dataRef = nil;
275 MovieImportComponent miComponent;
276 Track targetTrack = nil;
277 TimeValue addedDuration = 0;
278 long outFlags = 0;
279 OSErr err;
280 ComponentResult result;
281
282 myHandle = NewHandleClear((Size)m_waveLength);
283
284 BlockMove(m_hSnd, *myHandle, m_waveLength);
285
286 err = PtrToHand(&myHandle, &dataRef, sizeof(Handle));
287
288 if (memcmp(&m_hSnd[8], "WAVE", 4) == 0)
289 miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeWave);
290 else if (memcmp(&m_hSnd[8], "AIFF", 4) == 0)
291 miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFF);
292 else if (memcmp(&m_hSnd[8], "AIFC", 4) == 0)
293 miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFC);
294 else
295 {
296 wxLogSysError("wxSound - Location in memory does not contain valid data");
297 return false;
298 }
299
300 movie = NewMovie(0);
301
302 result = MovieImportDataRef(miComponent, dataRef,
303 HandleDataHandlerSubType, movie,
304 nil, &targetTrack,
305 nil, &addedDuration,
306 movieImportCreateTrack, &outFlags);
307
308 if (result != noErr)
309 {
310 wxLogSysError(wxString::Format(wxT("Couldn't import movie data\nError:%i"), (int)result));
311 }
312
313 SetMovieVolume(movie, kFullVolume);
314 GoToBeginningOfMovie(movie);
315
316 DisposeHandle(myHandle);
317 }
318 break;
319 case wxSound_RESOURCE:
320 {
321 SoundComponentData data;
322 unsigned long numframes, offset;
323
324 ParseSndHeader((SndListHandle)m_hSnd, &data, &numframes, &offset);
325 //m_waveLength = numFrames * data.numChannels;
326
327 SndChannelPtr pSndChannel;
328 SndNewChannel(&pSndChannel, sampledSynth,
329 initNoInterp +
330 (data.numChannels == 1 ? initMono : initStereo), NULL);
331
332 if(SndPlay(pSndChannel, (SndListHandle) m_hSnd, flags & wxSOUND_ASYNC ? 1 : 0) != noErr)
333 return false;
334
335 if (flags & wxSOUND_ASYNC)
336 {
337 ((wxSMTimer*&)m_pTimer) = new wxSMTimer(pSndChannel, m_hSnd, flags & wxSOUND_LOOP ? 1 : 0);
338
339 ((wxTimer*)m_pTimer)->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
340 }
341 else
342 SndDisposeChannel(pSndChannel, TRUE);
343
344 return true;
345 }
346 break;
347 case wxSound_FILE:
348 {
349 short movieResFile;
350 FSSpec sfFile;
351
352 #ifdef __WXMAC__
353 wxMacFilename2FSSpec( m_sndname , &sfFile ) ;
354 #else
355 int nError;
356 if ((nError = NativePathNameToFSSpec ((char*) m_sndname.c_str(), &sfFile, 0)) != noErr)
357 {
358 wxLogSysError(wxString::Format(wxT("File:%s does not exist\nError:%i"),
359 m_sndname.c_str(), nError));
360 return false;
361 }
362 #endif
363
364 if (OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr)
365 {
366 wxLogSysError(wxT("Quicktime couldn't open the file"));
367 return false;
368 }
369
370
371 short movieResID = 0;
372 Str255 movieName;
373 OSErr err;
374
375 err = NewMovieFromFile (
376 &movie,
377 movieResFile,
378 &movieResID,
379 movieName,
380 newMovieActive,
381 NULL); //wasChanged
382
383 CloseMovieFile (movieResFile);
384
385 if (err != noErr)
386 {
387 wxLogSysError(
388 wxString::Format(wxT("wxSound - Could not open file: %s\nError:%i"), m_sndname.c_str(), err )
389 );
390 return false;
391 }
392 }
393 break;
394 default:
395 return false;
396 }//end switch(m_type)
397
398
399 //Start the movie!
400 StartMovie(movie);
401
402 if (flags & wxSOUND_ASYNC)
403 {
404 //Start timer and play movie asyncronously
405 ((wxQTTimer*&)m_pTimer) = new wxQTTimer(movie, flags & wxSOUND_LOOP ? 1 : 0);
406 ((wxQTTimer*)m_pTimer)->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS);
407 }
408 else
409 {
410 wxASSERT_MSG(!(flags & wxSOUND_LOOP), "Can't loop and play syncronously at the same time");
411
412 //Play movie until it ends, then exit
413 while (!IsMovieDone(movie))
414 MoviesTask(movie, 0);
415
416 DisposeMovie(movie);
417 }
418
419 return true;
420 }
421
422 void* wxSound::GetHandle()
423 {
424 return (void*) ((wxQTTimer*) m_pTimer)->GetMovie();
425 }
426
427 bool wxSound::FreeData()
428 {
429 if (m_pTimer != NULL)
430 {
431 delete (wxQTTimer*) m_pTimer;
432 m_pTimer = NULL;
433 }
434
435 return true;
436 }
437 #endif //wxUSE_SOUND
438
439
440