1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/sound.cpp
3 // Purpose: wxSound class implementation: optional
5 // Modified by: Stefan Csomor
8 // Copyright: (c) Ryan Norton
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
17 #if wxOSX_USE_QUICKTIME
22 #include "wx/object.h"
23 #include "wx/string.h"
31 // Carbon QT Implementation Details -
34 // 1) OpenDefaultComponent(MovieImportType, kQTFileTypeWave);
36 // 3) MovieImportDataRef() //Pass Memory Location to this
38 // 5) IsMovieDone(), MoviesTask() //2nd param is minimum wait time to allocate to quicktime
41 // 1) Path as CFString
42 // 2) Call QTNewDataReferenceFromFullPathCFString
43 // 3) Call NewMovieFromDataRef
44 // 4) Call CloseMovieFile
46 // 5) IsMovieDone(), MoviesTask() //2nd param is minimum wait time to allocate to quicktime
50 #include "wx/osx/private.h"
51 #if wxOSX_USE_COCOA_OR_CARBON
52 #include <QuickTime/QuickTimeComponents.h>
58 #define MOVIE_DELAY 100
60 // ------------------------------------------------------------------
62 // ------------------------------------------------------------------
64 class wxOSXSoundManagerSoundData
: public wxSoundData
67 wxOSXSoundManagerSoundData(const wxString
& fileName
);
68 ~wxOSXSoundManagerSoundData();
70 virtual bool Play(unsigned flags
);
71 virtual void SoundTask();
76 SndChannelPtr m_pSndChannel
;
79 wxOSXSoundManagerSoundData::wxOSXSoundManagerSoundData(const wxString
& fileName
) :
84 wxMacStringToPascal( fileName
, lpSnd
) ;
86 m_hSnd
= (SndListHandle
) GetNamedResource('snd ', (const unsigned char *) lpSnd
);
89 wxOSXSoundManagerSoundData::~wxOSXSoundManagerSoundData()
92 ReleaseResource((Handle
)m_hSnd
);
95 void wxOSXSoundManagerSoundData::DoStop()
99 SndDisposeChannel(m_pSndChannel
, TRUE
/* stop immediately, not after playing */);
100 m_pSndChannel
= NULL
;
101 wxSound::SoundStopped(this);
105 bool wxOSXSoundManagerSoundData::Play(unsigned flags
)
111 SoundComponentData data
;
112 unsigned long numframes
, offset
;
114 ParseSndHeader((SndListHandle
)m_hSnd
, &data
, &numframes
, &offset
);
116 SndNewChannel(&m_pSndChannel
, sampledSynth
,
118 + (data
.numChannels
== 1 ? initMono
: initStereo
), NULL
);
120 if(SndPlay(m_pSndChannel
, (SndListHandle
) m_hSnd
, flags
& wxSOUND_ASYNC
? 1 : 0) != noErr
)
123 if (flags
& wxSOUND_ASYNC
)
124 CreateAndStartTimer();
131 void wxOSXSoundManagerSoundData::SoundTask()
135 if (SndChannelStatus((SndChannelPtr
)m_pSndChannel
, sizeof(SCStatus
), &stat
) != 0)
138 //if the sound isn't playing anymore, see if it's looped,
139 //and if so play it again, otherwise close things up
140 if (stat
.scChannelBusy
== FALSE
)
142 if (m_flags
& wxSOUND_LOOP
)
144 if(SndPlay((SndChannelPtr
)m_pSndChannel
, (SndListHandle
) m_hSnd
, true) != noErr
)
152 // ------------------------------------------------------------------
154 // ------------------------------------------------------------------
162 if ((nError
= InitializeQTML(0)) != noErr
)
164 wxLogSysError(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError
));
175 //Note that ExitMovies() is not necessary, but
176 //the docs are fuzzy on whether or not TerminateQTML is
184 class wxOSXQuickTimeSoundData
: public wxSoundData
187 wxOSXQuickTimeSoundData(const wxString
& fileName
);
188 wxOSXQuickTimeSoundData(int size
, const wxByte
* data
);
189 ~wxOSXQuickTimeSoundData();
191 virtual bool Play(unsigned flags
);
192 virtual void SoundTask();
193 virtual void DoStop();
197 wxString m_sndname
; //file path
198 Handle m_soundHandle
;
202 wxOSXQuickTimeSoundData::wxOSXQuickTimeSoundData(const wxString
& fileName
) :
203 m_movie(NULL
), m_soundHandle(NULL
)
205 m_sndname
= fileName
;
208 wxOSXQuickTimeSoundData::wxOSXQuickTimeSoundData(int size
, const wxByte
* data
) :
211 m_soundHandle
= NewHandleClear((Size
)size
);
212 BlockMove(data
, *m_soundHandle
, size
);
215 wxOSXQuickTimeSoundData::~wxOSXQuickTimeSoundData()
218 DisposeHandle(m_soundHandle
);
221 bool wxOSXQuickTimeSoundData::Play(unsigned flags
)
233 Handle dataRef
= nil
;
234 MovieImportComponent miComponent
;
235 Track targetTrack
= nil
;
236 TimeValue addedDuration
= 0;
239 ComponentResult result
;
241 err
= PtrToHand(&m_soundHandle
, &dataRef
, sizeof(Handle
));
243 HLock(m_soundHandle
);
244 if (memcmp(&(*m_soundHandle
)[8], "WAVE", 4) == 0)
245 miComponent
= OpenDefaultComponent(MovieImportType
, kQTFileTypeWave
);
246 else if (memcmp(&(*m_soundHandle
)[8], "AIFF", 4) == 0)
247 miComponent
= OpenDefaultComponent(MovieImportType
, kQTFileTypeAIFF
);
248 else if (memcmp(&(*m_soundHandle
)[8], "AIFC", 4) == 0)
249 miComponent
= OpenDefaultComponent(MovieImportType
, kQTFileTypeAIFC
);
252 HUnlock(m_soundHandle
);
253 wxLogSysError(wxT("wxSound - Location in memory does not contain valid data"));
257 HUnlock(m_soundHandle
);
258 m_movie
= NewMovie(0);
260 result
= MovieImportDataRef(miComponent
, dataRef
,
261 HandleDataHandlerSubType
, m_movie
,
264 movieImportCreateTrack
, &outFlags
);
268 wxLogSysError(wxString::Format(wxT("Couldn't import movie data\nError:%i"), (int)result
));
271 SetMovieVolume(m_movie
, kFullVolume
);
272 GoToBeginningOfMovie(m_movie
);
278 Handle dataRef
= NULL
;
281 err
= QTNewDataReferenceFromFullPathCFString(wxCFStringRef(m_sndname
,wxLocale::GetSystemEncoding()),
282 (UInt32
)kQTNativeDefaultPathStyle
, 0, &dataRef
, &dataRefType
);
284 wxASSERT(err
== noErr
);
286 if (NULL
!= dataRef
|| err
!= noErr
)
288 err
= NewMovieFromDataRef( &m_movie
, newMovieDontAskUnresolvedDataRefs
, NULL
, dataRef
, dataRefType
);
289 wxASSERT(err
== noErr
);
290 DisposeHandle(dataRef
);
296 wxString::Format(wxT("wxSound - Could not open file: %s\nError:%i"), m_sndname
.c_str(), err
)
305 if (flags
& wxSOUND_ASYNC
)
307 CreateAndStartTimer();
311 wxASSERT_MSG(!(flags
& wxSOUND_LOOP
), wxT("Can't loop and play syncronously at the same time"));
313 //Play movie until it ends, then exit
314 //Note that due to quicktime caching this may not always
315 //work 100% correctly
316 while (!IsMovieDone(m_movie
))
317 MoviesTask(m_movie
, 1);
325 void wxOSXQuickTimeSoundData::DoStop()
330 DisposeMovie(m_movie
);
332 wxSound::SoundStopped(this);
337 void wxOSXQuickTimeSoundData::SoundTask()
339 if(IsMovieDone(m_movie
))
341 if (m_flags
& wxSOUND_LOOP
)
344 GoToBeginningOfMovie(m_movie
);
351 MoviesTask(m_movie
, MOVIE_DELAY
); //Give QT time to play movie
354 bool wxSound::Create(int size
, const wxByte
* data
)
356 m_data
= new wxOSXQuickTimeSoundData(size
,data
);
360 bool wxSound::Create(const wxString
& fileName
, bool isResource
)
363 m_data
= new wxOSXSoundManagerSoundData(fileName
);
365 m_data
= new wxOSXQuickTimeSoundData(fileName
);
369 #endif // wxOSX_USE_QUICKTIME