]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/sound.cpp
added assert to check for not-yet-implemented behavior of SetClippingRegion
[wxWidgets.git] / src / unix / sound.cpp
index 1fb4999964e7572ff536603a8a38343e6d7a30a8..0afab5a47be20af4ea990f0dc8ad1a8f6ab5179c 100644 (file)
@@ -1,26 +1,19 @@
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
-// Name:        sound.cpp
+// Name:        src/unix/sound.cpp
 // Purpose:     wxSound
 // Author:      Marcel Rasche, Vaclav Slavik
 // Modified by:
 // Created:     25/10/98
 // RCS-ID:      $Id$
 // Copyright:   (c) Julian Smart, Open Source Applications Foundation
 // Purpose:     wxSound
 // Author:      Marcel Rasche, Vaclav Slavik
 // Modified by:
 // Created:     25/10/98
 // RCS-ID:      $Id$
 // Copyright:   (c) Julian Smart, Open Source Applications Foundation
-// Licence:    wxWindows licence
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 /////////////////////////////////////////////////////////////////////////////
 
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-#pragma implementation "sound.h"
-#pragma implementation "soundbase.h"
-#endif
-
 // for compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 // for compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
-#include "wx/setup.h"
-
 #if defined(__BORLANDC__)
 #if defined(__BORLANDC__)
-#pragma hdrstop
+    #pragma hdrstop
 #endif
 
 #if wxUSE_SOUND
 #endif
 
 #if wxUSE_SOUND
     #include "wx/event.h"
     #include "wx/intl.h"
     #include "wx/log.h"
     #include "wx/event.h"
     #include "wx/intl.h"
     #include "wx/log.h"
+    #include "wx/module.h"
 #endif
 
 #include "wx/thread.h"
 #include "wx/file.h"
 #endif
 
 #include "wx/thread.h"
 #include "wx/file.h"
-#include "wx/module.h"
 #include "wx/sound.h"
 #include "wx/dynlib.h"
 
 #include "wx/sound.h"
 #include "wx/dynlib.h"
 
@@ -55,7 +48,7 @@ static wxMutex gs_soundMutex;
 // ----------------------------------------------------------------------------
 // wxSoundData
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // wxSoundData
 // ----------------------------------------------------------------------------
-  
+
 void wxSoundData::IncRef()
 {
 #if wxUSE_THREADS
 void wxSoundData::IncRef()
 {
 #if wxUSE_THREADS
@@ -123,7 +116,7 @@ public:
 private:
     int OpenDSP(const wxSoundData *data);
     bool InitDSP(int dev, const wxSoundData *data);
 private:
     int OpenDSP(const wxSoundData *data);
     bool InitDSP(int dev, const wxSoundData *data);
-    
+
     int m_DSPblkSize;        // Size of the DSP buffer
     bool m_needConversion;
 };
     int m_DSPblkSize;        // Size of the DSP buffer
     bool m_needConversion;
 };
@@ -142,7 +135,7 @@ bool wxSoundBackendOSS::Play(wxSoundData *data, unsigned flags,
                              volatile wxSoundPlaybackStatus *status)
 {
     int dev = OpenDSP(data);
                              volatile wxSoundPlaybackStatus *status)
 {
     int dev = OpenDSP(data);
-    
+
     if (dev < 0)
         return false;
 
     if (dev < 0)
         return false;
 
@@ -173,7 +166,7 @@ bool wxSoundBackendOSS::Play(wxSoundData *data, unsigned flags,
             l += i;
         } while (play && l < datasize);
     } while (flags & wxSOUND_LOOP);
             l += i;
         } while (play && l < datasize);
     } while (flags & wxSOUND_LOOP);
-    
+
     close(dev);
     return true;
 }
     close(dev);
     return true;
 }
@@ -181,10 +174,10 @@ bool wxSoundBackendOSS::Play(wxSoundData *data, unsigned flags,
 int wxSoundBackendOSS::OpenDSP(const wxSoundData *data)
 {
     int dev = -1;
 int wxSoundBackendOSS::OpenDSP(const wxSoundData *data)
 {
     int dev = -1;
-  
+
     if ((dev = open(AUDIODEV, O_WRONLY, 0)) <0)
         return -1;
     if ((dev = open(AUDIODEV, O_WRONLY, 0)) <0)
         return -1;
-  
+
     if (!InitDSP(dev, data) || m_needConversion)
     {
         close(dev);
     if (!InitDSP(dev, data) || m_needConversion)
     {
         close(dev);
@@ -207,7 +200,7 @@ bool wxSoundBackendOSS::InitDSP(int dev, const wxSoundData *data)
     }
 
     m_needConversion = false;
     }
 
     m_needConversion = false;
-                
+
     tmp = data->m_bitsPerSample;
     if (ioctl(dev, SNDCTL_DSP_SAMPLESIZE, &tmp) < 0)
     {
     tmp = data->m_bitsPerSample;
     if (ioctl(dev, SNDCTL_DSP_SAMPLESIZE, &tmp) < 0)
     {
@@ -220,8 +213,8 @@ bool wxSoundBackendOSS::InitDSP(int dev, const wxSoundData *data)
                    _T("Unable to set DSP sample size to %d (wants %d)"),
                    data->m_bitsPerSample, tmp);
         m_needConversion = true;
                    _T("Unable to set DSP sample size to %d (wants %d)"),
                    data->m_bitsPerSample, tmp);
         m_needConversion = true;
-    }        
-        
+    }
+
     unsigned stereo = data->m_channels == 1 ? 0 : 1;
     tmp = stereo;
     if (ioctl(dev, SNDCTL_DSP_STEREO, &tmp) < 0)
     unsigned stereo = data->m_channels == 1 ? 0 : 1;
     tmp = stereo;
     if (ioctl(dev, SNDCTL_DSP_STEREO, &tmp) < 0)
@@ -231,7 +224,7 @@ bool wxSoundBackendOSS::InitDSP(int dev, const wxSoundData *data)
     }
     if (tmp != stereo)
     {
     }
     if (tmp != stereo)
     {
-       wxLogTrace(_T("sound"), _T("Unable to set DSP to %s."), stereo?  _T("stereo"):_T("mono"));
+        wxLogTrace(_T("sound"), _T("Unable to set DSP to %s."), stereo?  _T("stereo"):_T("mono"));
         m_needConversion = true;
     }
 
         m_needConversion = true;
     }
 
@@ -249,13 +242,13 @@ bool wxSoundBackendOSS::InitDSP(int dev, const wxSoundData *data)
         // problems. Sound cards will sometimes use things like 44101 when you
         // ask for 44100.  No need overriding this and having strange output
         // file rates for something that we can't hear anyways.
         // problems. Sound cards will sometimes use things like 44101 when you
         // ask for 44100.  No need overriding this and having strange output
         // file rates for something that we can't hear anyways.
-       if (data->m_samplingRate - tmp > (tmp * .01) || 
-           tmp - data->m_samplingRate > (tmp * .01)) {
-           wxLogTrace(_T("sound"),
+        if (data->m_samplingRate - tmp > (tmp * .01) ||
+            tmp - data->m_samplingRate > (tmp * .01)) {
+            wxLogTrace(_T("sound"),
                        _T("Unable to set DSP sampling rate to %d (wants %d)"),
                        data->m_samplingRate, tmp);
             m_needConversion = true;
                        _T("Unable to set DSP sampling rate to %d (wants %d)"),
                        data->m_samplingRate, tmp);
             m_needConversion = true;
-       }
+        }
     }
 
     // Do this last because some drivers can adjust the buffer sized based on
     }
 
     // Do this last because some drivers can adjust the buffer sized based on
@@ -267,7 +260,7 @@ bool wxSoundBackendOSS::InitDSP(int dev, const wxSoundData *data)
     }
     return true;
 }
     }
     return true;
 }
-   
+
 #endif // HAVE_SYS_SOUNDCARD_H
 
 // ----------------------------------------------------------------------------
 #endif // HAVE_SYS_SOUNDCARD_H
 
 // ----------------------------------------------------------------------------
@@ -287,7 +280,7 @@ public:
                               wxSoundData *data, unsigned flags)
         : wxThread(), m_adapt(adaptor), m_data(data), m_flags(flags) {}
     virtual ExitCode Entry();
                               wxSoundData *data, unsigned flags)
         : wxThread(), m_adapt(adaptor), m_data(data), m_flags(flags) {}
     virtual ExitCode Entry();
-    
+
 protected:
     wxSoundSyncOnlyAdaptor *m_adapt;
     wxSoundData *m_data;
 protected:
     wxSoundSyncOnlyAdaptor *m_adapt;
     wxSoundData *m_data;
@@ -303,7 +296,7 @@ class wxSoundSyncOnlyAdaptor : public wxSoundBackend
 public:
     wxSoundSyncOnlyAdaptor(wxSoundBackend *backend)
         : m_backend(backend), m_playing(false) {}
 public:
     wxSoundSyncOnlyAdaptor(wxSoundBackend *backend)
         : m_backend(backend), m_playing(false) {}
-    ~wxSoundSyncOnlyAdaptor()
+    virtual ~wxSoundSyncOnlyAdaptor()
     {
         delete m_backend;
     }
     {
         delete m_backend;
     }
@@ -393,11 +386,11 @@ bool wxSoundSyncOnlyAdaptor::Play(wxSoundData *data, unsigned flags,
 void wxSoundSyncOnlyAdaptor::Stop()
 {
     wxLogTrace(_T("sound"), _T("asking audio to stop"));
 void wxSoundSyncOnlyAdaptor::Stop()
 {
     wxLogTrace(_T("sound"), _T("asking audio to stop"));
-    
+
 #if wxUSE_THREADS
     // tell the player thread (if running) to stop playback ASAP:
     m_status.m_stopRequested = true;
 #if wxUSE_THREADS
     // tell the player thread (if running) to stop playback ASAP:
     m_status.m_stopRequested = true;
-    
+
     // acquire the mutex to be sure no sound is being played, then
     // release it because we don't need it for anything (the effect of this
     // is that calling thread will wait until playback thread reacts to
     // acquire the mutex to be sure no sound is being played, then
     // release it because we don't need it for anything (the effect of this
     // is that calling thread will wait until playback thread reacts to
@@ -413,13 +406,13 @@ bool wxSoundSyncOnlyAdaptor::IsPlaying() const
 #if wxUSE_THREADS
     return m_status.m_playing;
 #else
 #if wxUSE_THREADS
     return m_status.m_playing;
 #else
-    return FALSE;
+    return false;
 #endif
 }
 
 
 // ----------------------------------------------------------------------------
 #endif
 }
 
 
 // ----------------------------------------------------------------------------
-// wxSound 
+// wxSound
 // ----------------------------------------------------------------------------
 
 wxSoundBackend *wxSound::ms_backend = NULL;
 // ----------------------------------------------------------------------------
 
 wxSoundBackend *wxSound::ms_backend = NULL;
@@ -452,34 +445,41 @@ wxSound::~wxSound()
     Free();
 }
 
     Free();
 }
 
-bool wxSound::Create(const wxString& fileName, bool isResource)
+bool wxSound::Create(const wxString& fileName,
+                     bool WXUNUSED_UNLESS_DEBUG(isResource))
 {
     wxASSERT_MSG( !isResource,
              _T("Loading sound from resources is only supported on Windows") );
 {
     wxASSERT_MSG( !isResource,
              _T("Loading sound from resources is only supported on Windows") );
+
     Free();
     Free();
-  
+
     wxFile fileWave;
     if (!fileWave.Open(fileName, wxFile::read))
     wxFile fileWave;
     if (!fileWave.Open(fileName, wxFile::read))
-       {
-            return false;
-       }
+    {
+        return false;
+    }
+
+    wxFileOffset lenOrig = fileWave.Length();
+    if ( lenOrig == wxInvalidOffset )
+        return false;
 
 
-    size_t len = fileWave.Length();
+    size_t len = wx_truncate_cast(size_t, lenOrig);
     wxUint8 *data = new wxUint8[len];
     wxUint8 *data = new wxUint8[len];
-    if (fileWave.Read(data, len) != len)
+    if ( fileWave.Read(data, len) != lenOrig )
     {
     {
+        delete [] data;
         wxLogError(_("Couldn't load sound data from '%s'."), fileName.c_str());
         return false;
     }
 
     if (!LoadWAV(data, len, false))
     {
         wxLogError(_("Couldn't load sound data from '%s'."), fileName.c_str());
         return false;
     }
 
     if (!LoadWAV(data, len, false))
     {
+        delete [] data;
         wxLogError(_("Sound file '%s' is in unsupported format."),
                    fileName.c_str());
         return false;
     }
         wxLogError(_("Sound file '%s' is in unsupported format."),
                    fileName.c_str());
         return false;
     }
-    
+
     return true;
 }
 
     return true;
 }
 
@@ -569,7 +569,7 @@ bool wxSound::Create(int size, const wxByte* data)
         wxLogTrace(_T("sound"), _T("unloading backend"));
 
         Stop();
         wxLogTrace(_T("sound"), _T("unloading backend"));
 
         Stop();
+
         delete ms_backend;
         ms_backend = NULL;
 #if wxUSE_LIBSDL && wxUSE_PLUGINS
         delete ms_backend;
         ms_backend = NULL;
 #if wxUSE_LIBSDL && wxUSE_PLUGINS
@@ -610,7 +610,7 @@ void wxSound::Free()
 }
 
 typedef struct
 }
 
 typedef struct
-{ 
+{
     wxUint32      uiSize;
     wxUint16      uiFormatTag;
     wxUint16      uiChannels;
     wxUint32      uiSize;
     wxUint16      uiFormatTag;
     wxUint16      uiChannels;
@@ -620,19 +620,36 @@ typedef struct
     wxUint16      uiBitsPerSample;
 } WAVEFORMAT;
 
     wxUint16      uiBitsPerSample;
 } WAVEFORMAT;
 
-#define MONO             1  // and stereo is 2 by wav format
 #define WAVE_FORMAT_PCM  1
 #define WAVE_INDEX       8
 #define FMT_INDEX       12
 
 bool wxSound::LoadWAV(const wxUint8 *data, size_t length, bool copyData)
 {
 #define WAVE_FORMAT_PCM  1
 #define WAVE_INDEX       8
 #define FMT_INDEX       12
 
 bool wxSound::LoadWAV(const wxUint8 *data, size_t length, bool copyData)
 {
-    WAVEFORMAT waveformat;
-    wxUint32 ul;
-
-    if (length < 32 + sizeof(WAVEFORMAT))
+    // the simplest wave file header consists of 44 bytes:
+    //
+    //      0   "RIFF"
+    //      4   file size - 8
+    //      8   "WAVE"
+    //
+    //      12  "fmt "
+    //      16  chunk size                  |
+    //      20  format tag                  |
+    //      22  number of channels          |
+    //      24  sample rate                 | WAVEFORMAT
+    //      28  average bytes per second    |
+    //      32  bytes per frame             |
+    //      34  bits per sample             |
+    //
+    //      36  "data"
+    //      40  number of data bytes
+    //      44  (wave signal) data
+    //
+    // so check that we have at least as much
+    if ( length < 44 )
         return false;
 
         return false;
 
+    WAVEFORMAT waveformat;
     memcpy(&waveformat, &data[FMT_INDEX + 4], sizeof(WAVEFORMAT));
     waveformat.uiSize = wxUINT32_SWAP_ON_BE(waveformat.uiSize);
     waveformat.uiFormatTag = wxUINT16_SWAP_ON_BE(waveformat.uiFormatTag);
     memcpy(&waveformat, &data[FMT_INDEX + 4], sizeof(WAVEFORMAT));
     waveformat.uiSize = wxUINT32_SWAP_ON_BE(waveformat.uiSize);
     waveformat.uiFormatTag = wxUINT16_SWAP_ON_BE(waveformat.uiFormatTag);
@@ -642,6 +659,14 @@ bool wxSound::LoadWAV(const wxUint8 *data, size_t length, bool copyData)
     waveformat.uiBlockAlign = wxUINT16_SWAP_ON_BE(waveformat.uiBlockAlign);
     waveformat.uiBitsPerSample = wxUINT16_SWAP_ON_BE(waveformat.uiBitsPerSample);
 
     waveformat.uiBlockAlign = wxUINT16_SWAP_ON_BE(waveformat.uiBlockAlign);
     waveformat.uiBitsPerSample = wxUINT16_SWAP_ON_BE(waveformat.uiBitsPerSample);
 
+    // get the sound data size
+    wxUint32 ul;
+    memcpy(&ul, &data[FMT_INDEX + waveformat.uiSize + 12], 4);
+    ul = wxUINT32_SWAP_ON_BE(ul);
+
+    if ( length < ul + FMT_INDEX + waveformat.uiSize + 16 )
+        return false;
+
     if (memcmp(data, "RIFF", 4) != 0)
         return false;
     if (memcmp(&data[WAVE_INDEX], "WAVE", 4) != 0)
     if (memcmp(data, "RIFF", 4) != 0)
         return false;
     if (memcmp(&data[WAVE_INDEX], "WAVE", 4) != 0)
@@ -650,20 +675,14 @@ bool wxSound::LoadWAV(const wxUint8 *data, size_t length, bool copyData)
         return false;
     if (memcmp(&data[FMT_INDEX + waveformat.uiSize + 8], "data", 4) != 0)
         return false;
         return false;
     if (memcmp(&data[FMT_INDEX + waveformat.uiSize + 8], "data", 4) != 0)
         return false;
-    memcpy(&ul,&data[FMT_INDEX + waveformat.uiSize + 12], 4);
-    ul = wxUINT32_SWAP_ON_BE(ul);
-    
-    //WAS: if (ul + FMT_INDEX + waveformat.uiSize + 16 != length)
-    if (ul + FMT_INDEX + waveformat.uiSize + 16 > length)
-        return false;
-  
+
     if (waveformat.uiFormatTag != WAVE_FORMAT_PCM)
         return false;
     if (waveformat.uiFormatTag != WAVE_FORMAT_PCM)
         return false;
-  
-    if (waveformat.ulSamplesPerSec != 
+
+    if (waveformat.ulSamplesPerSec !=
         waveformat.ulAvgBytesPerSec / waveformat.uiBlockAlign)
         return false;
         waveformat.ulAvgBytesPerSec / waveformat.uiBlockAlign)
         return false;
-    
+
     m_data = new wxSoundData;
     m_data->m_channels = waveformat.uiChannels;
     m_data->m_samplingRate = waveformat.ulSamplesPerSec;
     m_data = new wxSoundData;
     m_data->m_channels = waveformat.uiChannels;
     m_data->m_samplingRate = waveformat.ulSamplesPerSec;
@@ -679,7 +698,7 @@ bool wxSound::LoadWAV(const wxUint8 *data, size_t length, bool copyData)
     else
         m_data->m_dataWithHeader = (wxUint8*)data;
 
     else
         m_data->m_dataWithHeader = (wxUint8*)data;
 
-    m_data->m_data = 
+    m_data->m_data =
         (&m_data->m_dataWithHeader[FMT_INDEX + waveformat.uiSize + 8]);
 
     return true;
         (&m_data->m_dataWithHeader[FMT_INDEX + waveformat.uiSize + 8]);
 
     return true;