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