]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/osx/carbon/sound.cpp
Make @genericAppearance Doxygen macro consistent with @appearance.
[wxWidgets.git] / src / osx / carbon / sound.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/osx/carbon/sound.cpp
3// Purpose: wxSound class implementation: optional
4// Author: Ryan Norton
5// Modified by: Stefan Csomor
6// Created: 1998-01-01
7// Copyright: (c) Ryan Norton
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// For compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#if wxUSE_SOUND
15
16#if wxOSX_USE_QUICKTIME
17
18#include "wx/sound.h"
19
20#ifndef WX_PRECOMP
21 #include "wx/object.h"
22 #include "wx/string.h"
23 #include "wx/intl.h"
24 #include "wx/log.h"
25 #include "wx/timer.h"
26#endif
27
28#include "wx/file.h"
29
30// Carbon QT Implementation Details -
31//
32// Memory:
33// 1) OpenDefaultComponent(MovieImportType, kQTFileTypeWave);
34// 2) NewMovie(0);
35// 3) MovieImportDataRef() //Pass Memory Location to this
36// 4) PlayMovie();
37// 5) IsMovieDone(), MoviesTask() //2nd param is minimum wait time to allocate to quicktime
38//
39// File:
40// 1) Path as CFString
41// 2) Call QTNewDataReferenceFromFullPathCFString
42// 3) Call NewMovieFromDataRef
43// 4) Call CloseMovieFile
44// 4) PlayMovie();
45// 5) IsMovieDone(), MoviesTask() //2nd param is minimum wait time to allocate to quicktime
46//
47
48#ifdef __WXMAC__
49 #include "wx/osx/private.h"
50 #if wxOSX_USE_COCOA_OR_CARBON
51 #include <QuickTime/QuickTimeComponents.h>
52 #endif
53#else
54 #include <qtml.h>
55#endif
56
57#define MOVIE_DELAY 100
58
59// ------------------------------------------------------------------
60// SoundManager
61// ------------------------------------------------------------------
62
63class wxOSXSoundManagerSoundData : public wxSoundData
64{
65public:
66 wxOSXSoundManagerSoundData(const wxString& fileName);
67 ~wxOSXSoundManagerSoundData();
68
69 virtual bool Play(unsigned flags);
70 virtual void SoundTask();
71
72 void DoStop();
73protected:
74 SndListHandle m_hSnd;
75 SndChannelPtr m_pSndChannel;
76};
77
78wxOSXSoundManagerSoundData::wxOSXSoundManagerSoundData(const wxString& fileName) :
79 m_pSndChannel(NULL)
80{
81 Str255 lpSnd ;
82
83 wxMacStringToPascal( fileName , lpSnd ) ;
84
85 m_hSnd = (SndListHandle) GetNamedResource('snd ', (const unsigned char *) lpSnd);
86}
87
88wxOSXSoundManagerSoundData::~wxOSXSoundManagerSoundData()
89{
90 DoStop();
91 ReleaseResource((Handle)m_hSnd);
92}
93
94void wxOSXSoundManagerSoundData::DoStop()
95{
96 if ( m_pSndChannel )
97 {
98 SndDisposeChannel(m_pSndChannel, TRUE /* stop immediately, not after playing */);
99 m_pSndChannel = NULL;
100 wxSound::SoundStopped(this);
101 }
102
103 if (IsMarkedForDeletion())
104 delete this;
105}
106
107bool wxOSXSoundManagerSoundData::Play(unsigned flags)
108{
109 Stop();
110
111 m_flags = flags;
112
113 SoundComponentData data;
114 unsigned long numframes, offset;
115
116 ParseSndHeader((SndListHandle)m_hSnd, &data, &numframes, &offset);
117
118 SndNewChannel(&m_pSndChannel, sampledSynth,
119 initNoInterp
120 + (data.numChannels == 1 ? initMono : initStereo), NULL);
121
122 if(SndPlay(m_pSndChannel, (SndListHandle) m_hSnd, flags & wxSOUND_ASYNC ? 1 : 0) != noErr)
123 return false;
124
125 if (flags & wxSOUND_ASYNC)
126 CreateAndStartTimer();
127 else
128 DoStop();
129
130 return true;
131}
132
133void wxOSXSoundManagerSoundData::SoundTask()
134{
135 SCStatus stat;
136
137 if (SndChannelStatus((SndChannelPtr)m_pSndChannel, sizeof(SCStatus), &stat) != 0)
138 Stop();
139
140 //if the sound isn't playing anymore, see if it's looped,
141 //and if so play it again, otherwise close things up
142 if (stat.scChannelBusy == FALSE)
143 {
144 if (m_flags & wxSOUND_LOOP)
145 {
146 if(SndPlay((SndChannelPtr)m_pSndChannel, (SndListHandle) m_hSnd, true) != noErr)
147 Stop();
148 }
149 else
150 Stop();
151 }
152}
153
154// ------------------------------------------------------------------
155// QuickTime
156// ------------------------------------------------------------------
157
158bool wxInitQT();
159bool wxInitQT()
160{
161#ifndef __WXMAC__
162 int nError;
163 //-2093 no dll
164 if ((nError = InitializeQTML(0)) != noErr)
165 {
166 wxLogSysError(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError));
167 return false;
168 }
169#endif
170 EnterMovies();
171 return true;
172}
173
174void wxExitQT();
175void wxExitQT()
176{
177 //Note that ExitMovies() is not necessary, but
178 //the docs are fuzzy on whether or not TerminateQTML is
179 ExitMovies();
180
181#ifndef __WXMAC__
182 TerminateQTML();
183#endif
184}
185
186class wxOSXQuickTimeSoundData : public wxSoundData
187{
188public:
189 wxOSXQuickTimeSoundData(const wxString& fileName);
190 wxOSXQuickTimeSoundData(size_t size, const void* data);
191 ~wxOSXQuickTimeSoundData();
192
193 virtual bool Play(unsigned flags);
194 virtual void SoundTask();
195 virtual void DoStop();
196protected:
197 Movie m_movie;
198
199 wxString m_sndname; //file path
200 Handle m_soundHandle;
201};
202
203
204wxOSXQuickTimeSoundData::wxOSXQuickTimeSoundData(const wxString& fileName) :
205 m_movie(NULL), m_soundHandle(NULL)
206{
207 m_sndname = fileName;
208}
209
210wxOSXQuickTimeSoundData::wxOSXQuickTimeSoundData(size_t size, const void* data) :
211 m_movie(NULL)
212{
213 m_soundHandle = NewHandleClear((Size)size);
214 BlockMove(data, *m_soundHandle, size);
215}
216
217wxOSXQuickTimeSoundData::~wxOSXQuickTimeSoundData()
218{
219 if ( m_soundHandle )
220 DisposeHandle(m_soundHandle);
221}
222
223bool wxOSXQuickTimeSoundData::Play(unsigned flags)
224{
225 if ( m_movie )
226 Stop();
227
228 m_flags = flags;
229
230 if (!wxInitQT())
231 return false;
232
233 if( m_soundHandle )
234 {
235 Handle dataRef = nil;
236 MovieImportComponent miComponent;
237 Track targetTrack = nil;
238 TimeValue addedDuration = 0;
239 long outFlags = 0;
240 OSErr err;
241 ComponentResult result;
242
243 err = PtrToHand(&m_soundHandle, &dataRef, sizeof(Handle));
244
245 HLock(m_soundHandle);
246 if (memcmp(&(*m_soundHandle)[8], "WAVE", 4) == 0)
247 miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeWave);
248 else if (memcmp(&(*m_soundHandle)[8], "AIFF", 4) == 0)
249 miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFF);
250 else if (memcmp(&(*m_soundHandle)[8], "AIFC", 4) == 0)
251 miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFC);
252 else
253 {
254 HUnlock(m_soundHandle);
255 wxLogSysError(wxT("wxSound - Location in memory does not contain valid data"));
256 return false;
257 }
258
259 HUnlock(m_soundHandle);
260 m_movie = NewMovie(0);
261
262 result = MovieImportDataRef(miComponent, dataRef,
263 HandleDataHandlerSubType, m_movie,
264 nil, &targetTrack,
265 nil, &addedDuration,
266 movieImportCreateTrack, &outFlags);
267
268 if (result != noErr)
269 {
270 wxLogSysError(wxString::Format(wxT("Couldn't import movie data\nError:%i"), (int)result));
271 }
272
273 SetMovieVolume(m_movie, kFullVolume);
274 GoToBeginningOfMovie(m_movie);
275 }
276 else
277 {
278 OSErr err = noErr ;
279
280 Handle dataRef = NULL;
281 OSType dataRefType;
282
283 err = QTNewDataReferenceFromFullPathCFString(wxCFStringRef(m_sndname,wxLocale::GetSystemEncoding()),
284 (UInt32)kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType);
285
286 wxASSERT(err == noErr);
287
288 if (NULL != dataRef || err != noErr)
289 {
290 err = NewMovieFromDataRef( &m_movie, newMovieDontAskUnresolvedDataRefs , NULL, dataRef, dataRefType );
291 wxASSERT(err == noErr);
292 DisposeHandle(dataRef);
293 }
294
295 if (err != noErr)
296 {
297 wxLogSysError(
298 wxString::Format(wxT("wxSound - Could not open file: %s\nError:%i"), m_sndname.c_str(), err )
299 );
300 return false;
301 }
302 }
303
304 //Start the m_movie!
305 StartMovie(m_movie);
306
307 if (flags & wxSOUND_ASYNC)
308 {
309 CreateAndStartTimer();
310 }
311 else
312 {
313 wxASSERT_MSG(!(flags & wxSOUND_LOOP), wxT("Can't loop and play syncronously at the same time"));
314
315 //Play movie until it ends, then exit
316 //Note that due to quicktime caching this may not always
317 //work 100% correctly
318 while (!IsMovieDone(m_movie))
319 MoviesTask(m_movie, 1);
320
321 DoStop();
322 }
323
324 return true;
325}
326
327void wxOSXQuickTimeSoundData::DoStop()
328{
329 if( m_movie )
330 {
331 StopMovie(m_movie);
332 DisposeMovie(m_movie);
333 m_movie = NULL;
334 wxSound::SoundStopped(this);
335 wxExitQT();
336 }
337}
338
339void wxOSXQuickTimeSoundData::SoundTask()
340{
341 if(IsMovieDone(m_movie))
342 {
343 if (m_flags & wxSOUND_LOOP)
344 {
345 StopMovie(m_movie);
346 GoToBeginningOfMovie(m_movie);
347 StartMovie(m_movie);
348 }
349 else
350 Stop();
351 }
352 else
353 MoviesTask(m_movie, MOVIE_DELAY); //Give QT time to play movie
354}
355
356bool wxSound::Create(size_t size, const void* data)
357{
358 m_data = new wxOSXQuickTimeSoundData(size,data);
359 return true;
360}
361
362bool wxSound::Create(const wxString& fileName, bool isResource)
363{
364 if ( isResource )
365 m_data = new wxOSXSoundManagerSoundData(fileName);
366 else
367 m_data = new wxOSXQuickTimeSoundData(fileName);
368 return true;
369}
370
371#endif // wxOSX_USE_QUICKTIME
372
373#endif //wxUSE_SOUND