1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/carbon/sound.cpp
3 // Purpose: wxSound class implementation: optional
5 // Modified by: Stefan Csomor
7 // Copyright: (c) Ryan Norton
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
16 #if wxOSX_USE_QUICKTIME
21 #include "wx/object.h"
22 #include "wx/string.h"
30 // Carbon QT Implementation Details -
33 // 1) OpenDefaultComponent(MovieImportType, kQTFileTypeWave);
35 // 3) MovieImportDataRef() //Pass Memory Location to this
37 // 5) IsMovieDone(), MoviesTask() //2nd param is minimum wait time to allocate to quicktime
40 // 1) Path as CFString
41 // 2) Call QTNewDataReferenceFromFullPathCFString
42 // 3) Call NewMovieFromDataRef
43 // 4) Call CloseMovieFile
45 // 5) IsMovieDone(), MoviesTask() //2nd param is minimum wait time to allocate to quicktime
49 #include "wx/osx/private.h"
50 #if wxOSX_USE_COCOA_OR_CARBON
51 #include <QuickTime/QuickTimeComponents.h>
57 #define MOVIE_DELAY 100
59 // ------------------------------------------------------------------
61 // ------------------------------------------------------------------
63 class wxOSXSoundManagerSoundData
: public wxSoundData
66 wxOSXSoundManagerSoundData(const wxString
& fileName
);
67 ~wxOSXSoundManagerSoundData();
69 virtual bool Play(unsigned flags
);
70 virtual void SoundTask();
75 SndChannelPtr m_pSndChannel
;
78 wxOSXSoundManagerSoundData::wxOSXSoundManagerSoundData(const wxString
& fileName
) :
83 wxMacStringToPascal( fileName
, lpSnd
) ;
85 m_hSnd
= (SndListHandle
) GetNamedResource('snd ', (const unsigned char *) lpSnd
);
88 wxOSXSoundManagerSoundData::~wxOSXSoundManagerSoundData()
91 ReleaseResource((Handle
)m_hSnd
);
94 void wxOSXSoundManagerSoundData::DoStop()
98 SndDisposeChannel(m_pSndChannel
, TRUE
/* stop immediately, not after playing */);
100 wxSound::SoundStopped(this);
103 if (IsMarkedForDeletion())
107 bool wxOSXSoundManagerSoundData::Play(unsigned flags
)
113 SoundComponentData data
;
114 unsigned long numframes
, offset
;
116 ParseSndHeader((SndListHandle
)m_hSnd
, &data
, &numframes
, &offset
);
118 SndNewChannel(&m_pSndChannel
, sampledSynth
,
120 + (data
.numChannels
== 1 ? initMono
: initStereo
), NULL
);
122 if(SndPlay(m_pSndChannel
, (SndListHandle
) m_hSnd
, flags
& wxSOUND_ASYNC
? 1 : 0) != noErr
)
125 if (flags
& wxSOUND_ASYNC
)
126 CreateAndStartTimer();
133 void wxOSXSoundManagerSoundData::SoundTask()
137 if (SndChannelStatus((SndChannelPtr
)m_pSndChannel
, sizeof(SCStatus
), &stat
) != 0)
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
)
144 if (m_flags
& wxSOUND_LOOP
)
146 if(SndPlay((SndChannelPtr
)m_pSndChannel
, (SndListHandle
) m_hSnd
, true) != noErr
)
154 // ------------------------------------------------------------------
156 // ------------------------------------------------------------------
164 if ((nError
= InitializeQTML(0)) != noErr
)
166 wxLogSysError(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError
));
177 //Note that ExitMovies() is not necessary, but
178 //the docs are fuzzy on whether or not TerminateQTML is
186 class wxOSXQuickTimeSoundData
: public wxSoundData
189 wxOSXQuickTimeSoundData(const wxString
& fileName
);
190 wxOSXQuickTimeSoundData(size_t size
, const void* data
);
191 ~wxOSXQuickTimeSoundData();
193 virtual bool Play(unsigned flags
);
194 virtual void SoundTask();
195 virtual void DoStop();
199 wxString m_sndname
; //file path
200 Handle m_soundHandle
;
204 wxOSXQuickTimeSoundData::wxOSXQuickTimeSoundData(const wxString
& fileName
) :
205 m_movie(NULL
), m_soundHandle(NULL
)
207 m_sndname
= fileName
;
210 wxOSXQuickTimeSoundData::wxOSXQuickTimeSoundData(size_t size
, const void* data
) :
213 m_soundHandle
= NewHandleClear((Size
)size
);
214 BlockMove(data
, *m_soundHandle
, size
);
217 wxOSXQuickTimeSoundData::~wxOSXQuickTimeSoundData()
220 DisposeHandle(m_soundHandle
);
223 bool wxOSXQuickTimeSoundData::Play(unsigned flags
)
235 Handle dataRef
= nil
;
236 MovieImportComponent miComponent
;
237 Track targetTrack
= nil
;
238 TimeValue addedDuration
= 0;
241 ComponentResult result
;
243 err
= PtrToHand(&m_soundHandle
, &dataRef
, sizeof(Handle
));
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
);
254 HUnlock(m_soundHandle
);
255 wxLogSysError(wxT("wxSound - Location in memory does not contain valid data"));
259 HUnlock(m_soundHandle
);
260 m_movie
= NewMovie(0);
262 result
= MovieImportDataRef(miComponent
, dataRef
,
263 HandleDataHandlerSubType
, m_movie
,
266 movieImportCreateTrack
, &outFlags
);
270 wxLogSysError(wxString::Format(wxT("Couldn't import movie data\nError:%i"), (int)result
));
273 SetMovieVolume(m_movie
, kFullVolume
);
274 GoToBeginningOfMovie(m_movie
);
280 Handle dataRef
= NULL
;
283 err
= QTNewDataReferenceFromFullPathCFString(wxCFStringRef(m_sndname
,wxLocale::GetSystemEncoding()),
284 (UInt32
)kQTNativeDefaultPathStyle
, 0, &dataRef
, &dataRefType
);
286 wxASSERT(err
== noErr
);
288 if (NULL
!= dataRef
|| err
!= noErr
)
290 err
= NewMovieFromDataRef( &m_movie
, newMovieDontAskUnresolvedDataRefs
, NULL
, dataRef
, dataRefType
);
291 wxASSERT(err
== noErr
);
292 DisposeHandle(dataRef
);
298 wxString::Format(wxT("wxSound - Could not open file: %s\nError:%i"), m_sndname
.c_str(), err
)
307 if (flags
& wxSOUND_ASYNC
)
309 CreateAndStartTimer();
313 wxASSERT_MSG(!(flags
& wxSOUND_LOOP
), wxT("Can't loop and play syncronously at the same time"));
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);
327 void wxOSXQuickTimeSoundData::DoStop()
332 DisposeMovie(m_movie
);
334 wxSound::SoundStopped(this);
339 void wxOSXQuickTimeSoundData::SoundTask()
341 if(IsMovieDone(m_movie
))
343 if (m_flags
& wxSOUND_LOOP
)
346 GoToBeginningOfMovie(m_movie
);
353 MoviesTask(m_movie
, MOVIE_DELAY
); //Give QT time to play movie
356 bool wxSound::Create(size_t size
, const void* data
)
358 m_data
= new wxOSXQuickTimeSoundData(size
,data
);
362 bool wxSound::Create(const wxString
& fileName
, bool isResource
)
365 m_data
= new wxOSXSoundManagerSoundData(fileName
);
367 m_data
= new wxOSXQuickTimeSoundData(fileName
);
371 #endif // wxOSX_USE_QUICKTIME