X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/489468feaa08b8f504735eecca522fb8d0f825d2..6178debcd342963974dbdce6ac2ddb2fbe89e42a:/src/osx/carbon/sound.cpp diff --git a/src/osx/carbon/sound.cpp b/src/osx/carbon/sound.cpp index b3ff384fc8..39bb269856 100644 --- a/src/osx/carbon/sound.cpp +++ b/src/osx/carbon/sound.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: src/mac/carbon/sound.cpp +// Name: src/osx/carbon/sound.cpp // Purpose: wxSound class implementation: optional // Author: Ryan Norton // Modified by: Stefan Csomor @@ -14,6 +14,8 @@ #if wxUSE_SOUND +#if wxOSX_USE_QUICKTIME + #include "wx/sound.h" #ifndef WX_PRECOMP @@ -45,432 +47,328 @@ // #ifdef __WXMAC__ -#include "wx/mac/uma.h" -#ifndef __DARWIN__ -#include -#include -#endif -#endif - -#include - -//quicktime media layer only required for mac emulation on pc -#ifndef __WXMAC__ -#include -#endif - -#ifndef __DARWIN__ -#include + #include "wx/osx/private.h" + #if wxOSX_USE_COCOA_OR_CARBON + #include + #endif #else -#include + #include #endif -//Time between timer calls #define MOVIE_DELAY 100 -static wxTimer* lastSoundTimer=NULL; -static bool lastSoundIsPlaying=false; - -#if !defined(__LP64__) -#define USE_QUICKTIME 1 -#else -#define USE_QUICKTIME 0 -#endif - -#if USE_QUICKTIME // ------------------------------------------------------------------ -// wxQTTimer - Handle Asyncronous Playing +// SoundManager // ------------------------------------------------------------------ -class wxQTTimer : public wxTimer + +class wxOSXSoundManagerSoundData : public wxSoundData { public: - wxQTTimer(Movie movie, bool bLoop, bool* playing) : - m_movie(movie), m_bLoop(bLoop), m_pbPlaying(playing) - { - } - - virtual ~wxQTTimer() - { - if(m_pbPlaying) - *m_pbPlaying = false; - - StopMovie(m_movie); - DisposeMovie(m_movie); - Stop(); + wxOSXSoundManagerSoundData(const wxString& fileName); + ~wxOSXSoundManagerSoundData(); + + virtual bool Play(unsigned flags); + virtual void SoundTask(); - //Note that ExitMovies() is not necessary, but - //the docs are fuzzy on whether or not TerminateQTML is - ExitMovies(); + void DoStop(); +protected: + SndListHandle m_hSnd; + SndChannelPtr m_pSndChannel; +}; -#ifndef __WXMAC__ - TerminateQTML(); -#endif - } +wxOSXSoundManagerSoundData::wxOSXSoundManagerSoundData(const wxString& fileName) : + m_pSndChannel(NULL) +{ + Str255 lpSnd ; + + wxMacStringToPascal( fileName , lpSnd ) ; + + m_hSnd = (SndListHandle) GetNamedResource('snd ', (const unsigned char *) lpSnd); +} - void Shutdown() - { - delete this; - } +wxOSXSoundManagerSoundData::~wxOSXSoundManagerSoundData() +{ + DoStop(); + ReleaseResource((Handle)m_hSnd); +} - void Notify() +void wxOSXSoundManagerSoundData::DoStop() +{ + if ( m_pSndChannel ) { - if (m_pbPlaying && !*m_pbPlaying) - { - Shutdown(); - } - - if(IsMovieDone(m_movie)) - { - if (!m_bLoop) - Shutdown(); - else - { - StopMovie(m_movie); - GoToBeginningOfMovie(m_movie); - StartMovie(m_movie); - } - } - else - MoviesTask(m_movie, MOVIE_DELAY); //Give QT time to play movie + SndDisposeChannel(m_pSndChannel, TRUE /* stop immediately, not after playing */); + m_pSndChannel = NULL; + wxSound::SoundStopped(this); } + + if (IsMarkedForDeletion()) + delete this; +} +bool wxOSXSoundManagerSoundData::Play(unsigned flags) +{ + Stop(); - Movie& GetMovie() {return m_movie;} - -protected: - Movie m_movie; - bool m_bLoop; - -public: - bool* m_pbPlaying; + m_flags = flags; -}; + SoundComponentData data; + unsigned long numframes, offset; + + ParseSndHeader((SndListHandle)m_hSnd, &data, &numframes, &offset); + SndNewChannel(&m_pSndChannel, sampledSynth, + initNoInterp + + (data.numChannels == 1 ? initMono : initStereo), NULL); + + if(SndPlay(m_pSndChannel, (SndListHandle) m_hSnd, flags & wxSOUND_ASYNC ? 1 : 0) != noErr) + return false; + + if (flags & wxSOUND_ASYNC) + CreateAndStartTimer(); + else + DoStop(); + + return true; +} -class wxSMTimer : public wxTimer +void wxOSXSoundManagerSoundData::SoundTask() { -public: - wxSMTimer(void* hSnd, void* pSndChannel, bool bLoop, bool* playing) - : m_hSnd(hSnd), m_pSndChannel(pSndChannel), m_bLoop(bLoop), m_pbPlaying(playing) - { - } - - virtual ~wxSMTimer() - { - if(m_pbPlaying) - *m_pbPlaying = false; - SndDisposeChannel((SndChannelPtr)m_pSndChannel, TRUE); + SCStatus stat; + + if (SndChannelStatus((SndChannelPtr)m_pSndChannel, sizeof(SCStatus), &stat) != 0) Stop(); - } - - void Notify() + + //if the sound isn't playing anymore, see if it's looped, + //and if so play it again, otherwise close things up + if (stat.scChannelBusy == FALSE) { - if (m_pbPlaying && !*m_pbPlaying) - { - Shutdown(); - } - - SCStatus stat; - - if (SndChannelStatus((SndChannelPtr)m_pSndChannel, sizeof(SCStatus), &stat) != 0) - Shutdown(); - - //if the sound isn't playing anymore, see if it's looped, - //and if so play it again, otherwise close things up - if (stat.scChannelBusy == FALSE) + if (m_flags & wxSOUND_LOOP) { - if (m_bLoop) - { - if(SndPlay((SndChannelPtr)m_pSndChannel, (SndListHandle) m_hSnd, true) != noErr) - Shutdown(); - } - else - Shutdown(); + if(SndPlay((SndChannelPtr)m_pSndChannel, (SndListHandle) m_hSnd, true) != noErr) + Stop(); } + else + Stop(); } - - void Shutdown() - { - delete this; - } - - void* GetChannel() {return m_pSndChannel;} - -protected: - void* m_hSnd; - void* m_pSndChannel; - bool m_bLoop; - -public: - bool* m_pbPlaying; -}; +} // ------------------------------------------------------------------ -// wxSound +// QuickTime // ------------------------------------------------------------------ -//Determines whether version 4 of QT is installed -Boolean wxIsQuickTime4Installed (void) +bool wxInitQT(); +bool wxInitQT() { -#ifdef __WXMAC__ - short error; - long result; - - error = Gestalt (gestaltQuickTime, &result); - return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0400); -#else - return true; -#endif -} - -inline bool wxInitQT () -{ - if (wxIsQuickTime4Installed()) - { - #ifndef __WXMAC__ - int nError; - //-2093 no dll - if ((nError = InitializeQTML(0)) != noErr) - wxLogSysError(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError)); - #endif - EnterMovies(); - return true; - } - else +#ifndef __WXMAC__ + int nError; + //-2093 no dll + if ((nError = InitializeQTML(0)) != noErr) { - wxLogSysError(wxT("Quicktime is not installed, or Your Version of Quicktime is <= 4.")); + wxLogSysError(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError)); return false; } -} - #endif - -wxSound::wxSound() -: m_hSnd(NULL), m_waveLength(0), m_pTimer(NULL), m_type(wxSound_NONE) -{ + EnterMovies(); + return true; } -wxSound::wxSound(const wxString& sFileName, bool isResource) -: m_hSnd(NULL), m_waveLength(0), m_pTimer(NULL), m_type(wxSound_NONE) +void wxExitQT(); +void wxExitQT() { - Create(sFileName, isResource); + //Note that ExitMovies() is not necessary, but + //the docs are fuzzy on whether or not TerminateQTML is + ExitMovies(); + +#ifndef __WXMAC__ + TerminateQTML(); +#endif } -wxSound::wxSound(int size, const wxByte* data) -: m_hSnd((char*)data), m_waveLength(size), m_pTimer(NULL), m_type(wxSound_MEMORY) +class wxOSXQuickTimeSoundData : public wxSoundData { +public: + wxOSXQuickTimeSoundData(const wxString& fileName); + wxOSXQuickTimeSoundData(int size, const wxByte* data); + ~wxOSXQuickTimeSoundData(); + + virtual bool Play(unsigned flags); + virtual void SoundTask(); + virtual void DoStop(); +protected: + Movie m_movie; + + wxString m_sndname; //file path + Handle m_soundHandle; +}; + + +wxOSXQuickTimeSoundData::wxOSXQuickTimeSoundData(const wxString& fileName) : + m_movie(NULL), m_soundHandle(NULL) +{ + m_sndname = fileName; } -wxSound::~wxSound() -{ +wxOSXQuickTimeSoundData::wxOSXQuickTimeSoundData(int size, const wxByte* data) : + m_movie(NULL) +{ + m_soundHandle = NewHandleClear((Size)size); + BlockMove(data, *m_soundHandle, size); } -bool wxSound::Create(const wxString& fileName, bool isResource) +wxOSXQuickTimeSoundData::~wxOSXQuickTimeSoundData() { - Stop(); - - if (isResource) - { -#ifdef __WXMAC__ - m_type = wxSound_RESOURCE; - - Str255 lpSnd ; - - wxMacStringToPascal( fileName , lpSnd ) ; - - m_sndname = fileName; - m_hSnd = (char*) GetNamedResource('snd ', (const unsigned char *) lpSnd); -#else - return false; -#endif - } - else - { - m_type = wxSound_FILE; - m_sndname = fileName; - } - - return true; + if ( m_soundHandle ) + DisposeHandle(m_soundHandle); } -bool wxSound::DoPlay(unsigned flags) const +bool wxOSXQuickTimeSoundData::Play(unsigned flags) { - Stop(); - -#if USE_QUICKTIME - - Movie movie; + if ( m_movie ) + Stop(); + + m_flags = flags; + + if (!wxInitQT()) + return false; - switch(m_type) + if( m_soundHandle ) { - case wxSound_MEMORY: + Handle dataRef = nil; + MovieImportComponent miComponent; + Track targetTrack = nil; + TimeValue addedDuration = 0; + long outFlags = 0; + OSErr err; + ComponentResult result; + + err = PtrToHand(&m_soundHandle, &dataRef, sizeof(Handle)); + + HLock(m_soundHandle); + if (memcmp(&(*m_soundHandle)[8], "WAVE", 4) == 0) + miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeWave); + else if (memcmp(&(*m_soundHandle)[8], "AIFF", 4) == 0) + miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFF); + else if (memcmp(&(*m_soundHandle)[8], "AIFC", 4) == 0) + miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFC); + else { - if (!wxInitQT()) - return false; - Handle myHandle, dataRef = nil; - MovieImportComponent miComponent; - Track targetTrack = nil; - TimeValue addedDuration = 0; - long outFlags = 0; - OSErr err; - ComponentResult result; - - myHandle = NewHandleClear((Size)m_waveLength); - - BlockMove(m_hSnd, *myHandle, m_waveLength); - - err = PtrToHand(&myHandle, &dataRef, sizeof(Handle)); - - if (memcmp(&m_hSnd[8], "WAVE", 4) == 0) - miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeWave); - else if (memcmp(&m_hSnd[8], "AIFF", 4) == 0) - miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFF); - else if (memcmp(&m_hSnd[8], "AIFC", 4) == 0) - miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFC); - else - { - wxLogSysError(wxT("wxSound - Location in memory does not contain valid data")); - return false; - } - - movie = NewMovie(0); - - result = MovieImportDataRef(miComponent, dataRef, - HandleDataHandlerSubType, movie, - nil, &targetTrack, - nil, &addedDuration, - movieImportCreateTrack, &outFlags); - - if (result != noErr) - { - wxLogSysError(wxString::Format(wxT("Couldn't import movie data\nError:%i"), (int)result)); - } - - SetMovieVolume(movie, kFullVolume); - GoToBeginningOfMovie(movie); - - DisposeHandle(myHandle); + HUnlock(m_soundHandle); + wxLogSysError(wxT("wxSound - Location in memory does not contain valid data")); + return false; } - break; - case wxSound_RESOURCE: + + HUnlock(m_soundHandle); + m_movie = NewMovie(0); + + result = MovieImportDataRef(miComponent, dataRef, + HandleDataHandlerSubType, m_movie, + nil, &targetTrack, + nil, &addedDuration, + movieImportCreateTrack, &outFlags); + + if (result != noErr) { - SoundComponentData data; - unsigned long numframes, offset; - - ParseSndHeader((SndListHandle)m_hSnd, &data, &numframes, &offset); - //m_waveLength = numFrames * data.numChannels; - - SndChannelPtr pSndChannel; - SndNewChannel(&pSndChannel, sampledSynth, - initNoInterp - + (data.numChannels == 1 ? initMono : initStereo), NULL); - - if(SndPlay(pSndChannel, (SndListHandle) m_hSnd, flags & wxSOUND_ASYNC ? 1 : 0) != noErr) - return false; - - if (flags & wxSOUND_ASYNC) - { - lastSoundTimer = ((wxSMTimer*&)m_pTimer) - = new wxSMTimer(pSndChannel, m_hSnd, flags & wxSOUND_LOOP ? 1 : 0, - &lastSoundIsPlaying); - lastSoundIsPlaying = true; - - ((wxTimer*)m_pTimer)->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS); - } - else - SndDisposeChannel(pSndChannel, TRUE); - - return true; + wxLogSysError(wxString::Format(wxT("Couldn't import movie data\nError:%i"), (int)result)); } - break; - case wxSound_FILE: + + SetMovieVolume(m_movie, kFullVolume); + GoToBeginningOfMovie(m_movie); + } + else + { + OSErr err = noErr ; + + Handle dataRef = NULL; + OSType dataRefType; + + err = QTNewDataReferenceFromFullPathCFString(wxCFStringRef(m_sndname,wxLocale::GetSystemEncoding()), + (UInt32)kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType); + + wxASSERT(err == noErr); + + if (NULL != dataRef || err != noErr) { - if (!wxInitQT()) - return false; - - OSErr err = noErr ; - - Handle dataRef = NULL; - OSType dataRefType; - - err = QTNewDataReferenceFromFullPathCFString(wxCFStringRef(m_sndname,wxLocale::GetSystemEncoding()), - (UInt32)kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType); - + err = NewMovieFromDataRef( &m_movie, newMovieDontAskUnresolvedDataRefs , NULL, dataRef, dataRefType ); wxASSERT(err == noErr); - - if (NULL != dataRef || err != noErr) - { - err = NewMovieFromDataRef( &movie, newMovieDontAskUnresolvedDataRefs , NULL, dataRef, dataRefType ); - wxASSERT(err == noErr); - DisposeHandle(dataRef); - } - - if (err != noErr) - { - wxLogSysError( - wxString::Format(wxT("wxSound - Could not open file: %s\nError:%i"), m_sndname.c_str(), err ) - ); - return false; - } + DisposeHandle(dataRef); } - break; - default: - return false; - }//end switch(m_type) - - //Start the movie! - StartMovie(movie); - + + if (err != noErr) + { + wxLogSysError( + wxString::Format(wxT("wxSound - Could not open file: %s\nError:%i"), m_sndname.c_str(), err ) + ); + return false; + } + } + + //Start the m_movie! + StartMovie(m_movie); + if (flags & wxSOUND_ASYNC) { - //Start timer and play movie asyncronously - lastSoundTimer = ((wxQTTimer*&)m_pTimer) = - new wxQTTimer(movie, flags & wxSOUND_LOOP ? 1 : 0, - &lastSoundIsPlaying); - lastSoundIsPlaying = true; - ((wxQTTimer*)m_pTimer)->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS); + CreateAndStartTimer(); } else { wxASSERT_MSG(!(flags & wxSOUND_LOOP), wxT("Can't loop and play syncronously at the same time")); - + //Play movie until it ends, then exit //Note that due to quicktime caching this may not always //work 100% correctly - while (!IsMovieDone(movie)) - MoviesTask(movie, 1); - - DisposeMovie(movie); + while (!IsMovieDone(m_movie)) + MoviesTask(m_movie, 1); + + DoStop(); } -#endif - + return true; } -bool wxSound::IsPlaying() +void wxOSXQuickTimeSoundData::DoStop() { - return lastSoundIsPlaying; + if( m_movie ) + { + StopMovie(m_movie); + DisposeMovie(m_movie); + m_movie = NULL; + wxSound::SoundStopped(this); + wxExitQT(); + } } -void wxSound::Stop() +void wxOSXQuickTimeSoundData::SoundTask() { - if (lastSoundIsPlaying) + if(IsMovieDone(m_movie)) { - delete (wxTimer*&) lastSoundTimer; - lastSoundIsPlaying = false; - lastSoundTimer = NULL; + if (m_flags & wxSOUND_LOOP) + { + StopMovie(m_movie); + GoToBeginningOfMovie(m_movie); + StartMovie(m_movie); + } + else + Stop(); } + else + MoviesTask(m_movie, MOVIE_DELAY); //Give QT time to play movie } -void* wxSound::GetHandle() +bool wxSound::Create(int size, const wxByte* data) { -#if USE_QUICKTIME - if(m_type == wxSound_RESOURCE) - return (void*) ((wxSMTimer*)m_pTimer)->GetChannel(); + m_data = new wxOSXQuickTimeSoundData(size,data); + return true; +} - return (void*) ((wxQTTimer*) m_pTimer)->GetMovie(); -#endif - return NULL; +bool wxSound::Create(const wxString& fileName, bool isResource) +{ + if ( isResource ) + m_data = new wxOSXSoundManagerSoundData(fileName); + else + m_data = new wxOSXQuickTimeSoundData(fileName); + return true; } +#endif // wxOSX_USE_QUICKTIME + #endif //wxUSE_SOUND