X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/11df1e8a334a8ba81a3514994571be28613a66e9..2cf3a6d7bef6f20bea35062dd3d4dbf0aec9efb5:/src/mac/carbon/sound.cpp diff --git a/src/mac/carbon/sound.cpp b/src/mac/carbon/sound.cpp index 17e46752a8..f6ccb1557b 100644 --- a/src/mac/carbon/sound.cpp +++ b/src/mac/carbon/sound.cpp @@ -1,26 +1,30 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: sound.cpp +// Name: src/mac/carbon/sound.cpp // Purpose: wxSound class implementation: optional -// Author: Ryan Norton, Stefan Csomor -// Modified by: +// Author: Ryan Norton +// Modified by: Stefan Csomor // Created: 1998-01-01 // RCS-ID: $Id$ -// Copyright: (c) Ryan Norton, Stefan Csomor -// Licence: wxWindows licence +// Copyright: (c) Ryan Norton +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "sound.h" -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#if wxUSE_SOUND -#include "wx/object.h" -#include "wx/string.h" -#include "wx/log.h" -#include "wx/file.h" #include "wx/sound.h" -#include "wx/timer.h" -#if wxUSE_SOUND +#ifndef WX_PRECOMP + #include "wx/object.h" + #include "wx/string.h" + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/timer.h" +#endif + +#include "wx/file.h" // Carbon QT Implementation Details - // @@ -41,10 +45,12 @@ // #ifdef __WXMAC__ -#include "wx/mac/private.h" +#include "wx/mac/uma.h" +#ifndef __DARWIN__ #include #include #endif +#endif #if defined __WXMAC__ && defined __DARWIN__/*TARGET_CARBON*/ #ifdef __APPLE_CC__ @@ -61,37 +67,59 @@ #include #endif +#ifndef __DARWIN__ #include +#else +#include +#endif -//Time inbetween timer calls +//Time between timer calls #define MOVIE_DELAY 100 +static wxTimer* lastSoundTimer=NULL; +static bool lastSoundIsPlaying=false; + // ------------------------------------------------------------------ // wxQTTimer - Handle Asyncronous Playing // ------------------------------------------------------------------ class wxQTTimer : public wxTimer { public: - wxQTTimer(Movie movie, bool bLoop) : - m_movie(movie), m_bLoop(bLoop) + wxQTTimer(Movie movie, bool bLoop, bool* playing) : + m_movie(movie), m_bLoop(bLoop), m_pbPlaying(playing) { } ~wxQTTimer() { - Shutdown(); - } + if(m_pbPlaying) + *m_pbPlaying = false; - void Shutdown() - { StopMovie(m_movie); DisposeMovie(m_movie); - m_movie = NULL ; Stop(); + + //Note that ExitMovies() is not necessary, but + //the docs are fuzzy on whether or not TerminateQTML is + ExitMovies(); + +#ifndef __WXMAC__ + TerminateQTML(); +#endif + } + + void Shutdown() + { + delete this; } void Notify() { + if (m_pbPlaying && !*m_pbPlaying) + { + Shutdown(); + } + if(IsMovieDone(m_movie)) { if (!m_bLoop) @@ -99,9 +127,9 @@ public: else { StopMovie(m_movie); - GoToBeginningOfMovie(m_movie); + GoToBeginningOfMovie(m_movie); StartMovie(m_movie); - } + } } else MoviesTask(m_movie, MOVIE_DELAY); //Give QT time to play movie @@ -109,56 +137,73 @@ public: Movie& GetMovie() {return m_movie;} + protected: Movie m_movie; bool m_bLoop; + +public: + bool* m_pbPlaying; + }; class wxSMTimer : public wxTimer { public: - wxSMTimer(void* hSnd, void* pSndChannel, const bool& bLoop) - : m_hSnd(hSnd), m_pSndChannel(pSndChannel), m_bLoop(bLoop) - { - } + wxSMTimer(void* hSnd, void* pSndChannel, bool bLoop, bool* playing) + : m_hSnd(hSnd), m_pSndChannel(pSndChannel), m_bLoop(bLoop), m_pbPlaying(playing) + { + } ~wxSMTimer() - { - Shutdown(); - } + { + if(m_pbPlaying) + *m_pbPlaying = false; + SndDisposeChannel((SndChannelPtr)m_pSndChannel, TRUE); + Stop(); + } void Notify() + { + if (m_pbPlaying && !*m_pbPlaying) { - SCStatus stat; + 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_bLoop) - { - if(SndPlay((SndChannelPtr)m_pSndChannel, (SndListHandle) m_hSnd, true) != noErr) - Shutdown(); - } - else - Shutdown(); + 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_bLoop) + { + if(SndPlay((SndChannelPtr)m_pSndChannel, (SndListHandle) m_hSnd, true) != noErr) + Shutdown(); + } + else + Shutdown(); } } void Shutdown() { - SndDisposeChannel((SndChannelPtr)m_pSndChannel, TRUE); - Stop(); + delete this; } - + + void* GetChannel() {return m_pSndChannel;} + protected: void* m_hSnd; void* m_pSndChannel; bool m_bLoop; + +public: + bool* m_pbPlaying; }; // ------------------------------------------------------------------ @@ -173,7 +218,7 @@ Boolean wxIsQuickTime4Installed (void) long result; error = Gestalt (gestaltQuickTime, &result); - return (error == noErr) && (result >= 4); //result >= 4 correct? + return (error == noErr) && (((result >> 16) & 0xffff) >= 0x0400); #else return true; #endif @@ -187,16 +232,16 @@ inline bool wxInitQT () int nError; //-2093 no dll if ((nError = InitializeQTML(0)) != noErr) - wxLogSysError(wxString::Format("Couldn't Initialize Quicktime-%i", nError)); - #endif + wxLogSysError(wxString::Format(wxT("Couldn't Initialize Quicktime-%i"), nError)); + #endif EnterMovies(); return true; } else - { - wxLogSysError("Quicktime is not installed, or Your Version of Quicktime is <= 4."); - return false; - } + { + wxLogSysError(wxT("Quicktime is not installed, or Your Version of Quicktime is <= 4.")); + return false; + } } wxSound::wxSound() @@ -213,19 +258,15 @@ wxSound::wxSound(const wxString& sFileName, bool isResource) wxSound::wxSound(int size, const wxByte* data) : m_hSnd((char*)data), m_waveLength(size), m_pTimer(NULL), m_type(wxSound_MEMORY) { - if (!wxInitQT()) - m_type = wxSound_NONE; } wxSound::~wxSound() { - FreeData(); } bool wxSound::Create(const wxString& fileName, bool isResource) { - if(!wxInitQT()) - return false; + Stop(); if (isResource) { @@ -236,14 +277,14 @@ bool wxSound::Create(const wxString& fileName, bool isResource) wxMacStringToPascal( fileName , lpSnd ) ; - m_sndname = lpSnd; + m_sndname = fileName; m_hSnd = (char*) GetNamedResource('snd ', (const unsigned char *) lpSnd); #else return false; #endif - } - else - { + } + else + { m_type = wxSound_FILE; m_sndname = fileName; } @@ -253,7 +294,7 @@ bool wxSound::Create(const wxString& fileName, bool isResource) bool wxSound::DoPlay(unsigned flags) const { - wxASSERT(m_pTimer == NULL || !((wxTimer*)m_pTimer)->IsRunning() ); + Stop(); Movie movie; @@ -261,8 +302,10 @@ bool wxSound::DoPlay(unsigned flags) const { case wxSound_MEMORY: { + if (!wxInitQT()) + return false; Handle myHandle, dataRef = nil; - MovieImportComponent miComponent; + MovieImportComponent miComponent; Track targetTrack = nil; TimeValue addedDuration = 0; long outFlags = 0; @@ -270,7 +313,7 @@ bool wxSound::DoPlay(unsigned flags) const ComponentResult result; myHandle = NewHandleClear((Size)m_waveLength); - + BlockMove(m_hSnd, *myHandle, m_waveLength); err = PtrToHand(&myHandle, &dataRef, sizeof(Handle)); @@ -282,8 +325,8 @@ bool wxSound::DoPlay(unsigned flags) const else if (memcmp(&m_hSnd[8], "AIFC", 4) == 0) miComponent = OpenDefaultComponent(MovieImportType, kQTFileTypeAIFC); else - { - wxLogSysError("wxSound - Location in memory does not contain valid data"); + { + wxLogSysError(wxT("wxSound - Location in memory does not contain valid data")); return false; } @@ -298,10 +341,12 @@ bool wxSound::DoPlay(unsigned flags) const if (result != noErr) { wxLogSysError(wxString::Format(wxT("Couldn't import movie data\nError:%i"), (int)result)); - } + } SetMovieVolume(movie, kFullVolume); GoToBeginningOfMovie(movie); + + DisposeHandle(myHandle); } break; case wxSound_RESOURCE: @@ -314,19 +359,22 @@ bool wxSound::DoPlay(unsigned flags) const SndChannelPtr pSndChannel; SndNewChannel(&pSndChannel, sampledSynth, - initNoInterp + - (data.numChannels == 1 ? initMono : initStereo), NULL); + initNoInterp + + (data.numChannels == 1 ? initMono : initStereo), NULL); if(SndPlay(pSndChannel, (SndListHandle) m_hSnd, flags & wxSOUND_ASYNC ? 1 : 0) != noErr) - return false; + return false; if (flags & wxSOUND_ASYNC) - { - ((wxSMTimer*&)m_pTimer) = new wxSMTimer(pSndChannel, m_hSnd, flags & wxSOUND_LOOP ? 1 : 0); - - ((wxTimer*)m_pTimer)->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS); - } - else + { + 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; @@ -334,72 +382,113 @@ bool wxSound::DoPlay(unsigned flags) const break; case wxSound_FILE: { - short movieResFile; - FSSpec sfFile; + if (!wxInitQT()) + return false; + OSErr err = noErr ; +//NB: RN: Stefan - I think the 10.3 path functions are broken if kQTNativeDefaultPathStyle is +//going to trigger a warning every time it is used - where its _supposed to be used_!! +//(kQTNativePathStyle is negative but the function argument is unsigned!) +//../src/mac/carbon/sound.cpp: In member function `virtual bool +// wxSound::DoPlay(unsigned int) const': +//../src/mac/carbon/sound.cpp:387: warning: passing negative value ` +// kQTNativeDefaultPathStyle' for argument passing 2 of `OSErr +// QTNewDataReferenceFromFullPathCFString(const __CFString*, long unsigned int, +// long unsigned int, char***, OSType*)' +//../src/mac/carbon/sound.cpp:387: warning: argument of negative value ` +// kQTNativeDefaultPathStyle' to `long unsigned int' +#if defined( __WXMAC__ ) && TARGET_API_MAC_OSX && ( MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_2 ) + if ( UMAGetSystemVersion() >= 0x1030 ) + { + Handle dataRef = NULL; + OSType dataRefType; + + err = QTNewDataReferenceFromFullPathCFString(wxMacCFStringHolder(m_sndname,wxLocale::GetSystemEncoding()), + //FIXME: Why does this have to be casted? + (unsigned int)kQTNativeDefaultPathStyle, + //FIXME: End + 0, &dataRef, &dataRefType); + + wxASSERT(err == noErr); + + if (NULL != dataRef || err != noErr) + { + err = NewMovieFromDataRef( &movie, newMovieDontAskUnresolvedDataRefs , NULL, dataRef, dataRefType ); + wxASSERT(err == noErr); + DisposeHandle(dataRef); + } + } + else +#endif + { + short movieResFile; + FSSpec sfFile; #ifdef __WXMAC__ - wxMacFilename2FSSpec( m_sndname , &sfFile ) ; + wxMacFilename2FSSpec( m_sndname , &sfFile ) ; #else - int nError; - if ((nError = NativePathNameToFSSpec ((char*) m_sndname.c_str(), &sfFile, 0)) != noErr) - { - wxLogSysError(wxString::Format(wxT("File:%s does not exist\nError:%i"), - m_sndname.c_str(), nError)); - return false; - } + int nError; + if ((nError = NativePathNameToFSSpec ((char*) m_sndname.c_str(), &sfFile, 0)) != noErr) + { +/* + wxLogSysError(wxString::Format(wxT("File:%s does not exist\nError:%i"), + m_sndname.c_str(), nError)); +*/ + return false; + } #endif - - if (OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr) - { - wxLogSysError(wxT("Quicktime couldn't open the file")); - return false; + if (OpenMovieFile (&sfFile, &movieResFile, fsRdPerm) != noErr) + { + wxLogSysError(wxT("Quicktime couldn't open the file")); + return false; + } + short movieResID = 0; + Str255 movieName; + + err = NewMovieFromFile ( + &movie, + movieResFile, + &movieResID, + movieName, + newMovieActive, + NULL); //wasChanged + + CloseMovieFile (movieResFile); } - - short movieResID = 0; - Str255 movieName; - OSErr err; - - err = NewMovieFromFile ( - &movie, - movieResFile, - &movieResID, - movieName, - newMovieActive, - NULL); //wasChanged - - CloseMovieFile (movieResFile); - if (err != noErr) - { + { wxLogSysError( wxString::Format(wxT("wxSound - Could not open file: %s\nError:%i"), m_sndname.c_str(), err ) ); return false; - } + } } break; default: return false; }//end switch(m_type) - //Start the movie! StartMovie(movie); if (flags & wxSOUND_ASYNC) { //Start timer and play movie asyncronously - ((wxQTTimer*&)m_pTimer) = new wxQTTimer(movie, flags & wxSOUND_LOOP ? 1 : 0); + lastSoundTimer = ((wxQTTimer*&)m_pTimer) = + new wxQTTimer(movie, flags & wxSOUND_LOOP ? 1 : 0, + &lastSoundIsPlaying); + lastSoundIsPlaying = true; ((wxQTTimer*)m_pTimer)->Start(MOVIE_DELAY, wxTIMER_CONTINUOUS); } else { - wxASSERT_MSG(!(flags & wxSOUND_LOOP), "Can't loop and play syncronously at the same time"); + 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, 0); + MoviesTask(movie, 1); DisposeMovie(movie); } @@ -407,26 +496,27 @@ bool wxSound::DoPlay(unsigned flags) const return true; } -void* wxSound::GetHandle() +bool wxSound::IsPlaying() { - return (void*) ((wxQTTimer*) m_pTimer)->GetMovie(); + return lastSoundIsPlaying; } -bool wxSound::FreeData() +void wxSound::Stop() { - if (m_pTimer != NULL) + if (lastSoundIsPlaying) { - delete (wxQTTimer*) m_pTimer; - m_pTimer = NULL; + delete (wxTimer*&) lastSoundTimer; + lastSoundIsPlaying = false; + lastSoundTimer = NULL; } +} - //Note that ExitMovies() is not neccessary, but - //the docs are fuzzy on whether or not TerminateQTML is - ExitMovies(); +void* wxSound::GetHandle() +{ + if(m_type == wxSound_RESOURCE) + return (void*) ((wxSMTimer*)m_pTimer)->GetChannel(); -#ifndef __WXMAC__ - TerminateQTML(); -#endif - return true; + return (void*) ((wxQTTimer*) m_pTimer)->GetMovie(); } + #endif //wxUSE_SOUND