// Name: sound.cpp
// Purpose: wxSound
// Author: Julian Smart
-// Modified by:
+// Modified by: 2005-07-29: Vadim Zeitlin: redesign
// Created: 04/01/98
// RCS-ID: $Id$
// Copyright: (c) Julian Smart
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-#pragma implementation "sound.h"
-#endif
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if defined(__BORLANDC__)
-#pragma hdrstop
+ #pragma hdrstop
#endif
#if wxUSE_SOUND
-#ifndef WX_PRECOMP
-#include "wx/wx.h"
-#endif
-
-#include "wx/file.h"
#include "wx/sound.h"
#include "wx/msw/private.h"
-#include <windowsx.h>
+#include <mmsystem.h>
-#if defined(__GNUWIN32_OLD__) && !defined(__CYGWIN10__)
- #include "wx/msw/gnuwin32/extra.h"
-#else
- #include <mmsystem.h>
-#endif
+// ----------------------------------------------------------------------------
+// wxSoundData
+// ----------------------------------------------------------------------------
-wxSound::wxSound()
- : m_waveData(NULL), m_waveLength(0), m_isResource(false)
+// ABC for different sound data representations
+class wxSoundData
{
-}
+public:
+ wxSoundData() { }
-wxSound::wxSound(const wxString& sFileName, bool isResource)
- : m_waveData(NULL), m_waveLength(0), m_isResource(isResource)
+ // return true if we had been successfully initialized
+ virtual bool IsOk() const = 0;
+
+ // get the flag corresponding to our content for PlaySound()
+ virtual DWORD GetSoundFlag() const = 0;
+
+ // get the data to be passed to PlaySound()
+ virtual LPCTSTR GetSoundData() const = 0;
+
+ virtual ~wxSoundData() { }
+};
+
+// class for in-memory sound data
+class wxSoundDataMemory : public wxSoundData
{
- Create(sFileName, isResource);
-}
+public:
+ // we copy the data
+ wxSoundDataMemory(int size, const wxByte *buf);
+
+ void *GetPtr() const { return m_waveDataPtr; }
+
+ virtual bool IsOk() const { return GetPtr() != NULL; }
+ virtual DWORD GetSoundFlag() const { return SND_MEMORY; }
+ virtual LPCTSTR GetSoundData() const { return (LPCTSTR)GetPtr(); }
-wxSound::wxSound(int size, const wxByte* data)
- : m_waveData(NULL), m_waveLength(0), m_isResource(false)
+private:
+ GlobalPtr m_waveData;
+ GlobalPtrLock m_waveDataPtr;
+
+ wxDECLARE_NO_COPY_CLASS(wxSoundDataMemory);
+};
+
+// class for sound files and resources
+class wxSoundDataFile : public wxSoundData
+{
+public:
+ wxSoundDataFile(const wxString& filename, bool isResource);
+
+ virtual bool IsOk() const { return !m_name.empty(); }
+ virtual DWORD GetSoundFlag() const
+ {
+ return m_isResource ? SND_RESOURCE : SND_FILENAME;
+ }
+ virtual LPCTSTR GetSoundData() const { return m_name.c_str(); }
+
+private:
+ const wxString m_name;
+ const bool m_isResource;
+
+ wxDECLARE_NO_COPY_CLASS(wxSoundDataFile);
+};
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// wxSoundData-derived classes
+// ----------------------------------------------------------------------------
+
+wxSoundDataMemory::wxSoundDataMemory(int size, const wxByte *buf)
+ : m_waveData(size),
+ m_waveDataPtr(m_waveData)
{
- Create(size, data);
+ if ( IsOk() )
+ ::CopyMemory(m_waveDataPtr, buf, size);
}
-wxSound::~wxSound()
+wxSoundDataFile::wxSoundDataFile(const wxString& filename, bool isResource)
+ : m_name(filename),
+ m_isResource(isResource)
{
- Free();
+ // check for file/resource existence?
}
-bool wxSound::Create(const wxString& fileName, bool isResource)
+// ----------------------------------------------------------------------------
+// wxSound
+// ----------------------------------------------------------------------------
+
+wxSound::wxSound()
{
- Free();
+ Init();
+}
- if (isResource)
- {
- m_isResource = TRUE;
+wxSound::wxSound(const wxString& filename, bool isResource)
+{
+ Init();
+ Create(filename, isResource);
+}
- HRSRC hresInfo;
- hresInfo = ::FindResource((HMODULE) wxhInstance, fileName, wxT("WAVE"));
- if (!hresInfo)
- return false;
+wxSound::wxSound(int size, const wxByte *data)
+{
+ Init();
+ Create(size, data);
+}
- HGLOBAL waveData = ::LoadResource((HMODULE) wxhInstance, hresInfo);
+wxSound::~wxSound()
+{
+ Free();
+}
- if (waveData)
+void wxSound::Free()
+{
+ if ( m_data )
{
- m_waveData= (wxByte*)::LockResource(waveData);
- m_waveLength = (int) ::SizeofResource((HMODULE) wxhInstance, hresInfo);
+ delete m_data;
+ m_data = NULL;
}
+}
- return (m_waveData ? true : false);
- }
- else
- {
- m_isResource = false;
-
- wxFile fileWave;
- if (!fileWave.Open(fileName, wxFile::read))
- return false;
+bool wxSound::CheckCreatedOk()
+{
+ if ( m_data && !m_data->IsOk() )
+ Free();
- m_waveLength = (int) fileWave.Length();
+ return m_data != NULL;
+}
- m_waveData = (wxByte*)GlobalLock(GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, m_waveLength));
- if (!m_waveData)
- return false;
+bool wxSound::Create(const wxString& filename, bool isResource)
+{
+ Free();
- fileWave.Read(m_waveData, m_waveLength);
+ m_data = new wxSoundDataFile(filename, isResource);
- return true;
- }
+ return CheckCreatedOk();
}
bool wxSound::Create(int size, const wxByte* data)
{
- Free();
- m_isResource = true;
- m_waveLength=size;
- m_waveData = (wxByte*)GlobalLock(GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, m_waveLength));
- if (!m_waveData)
- return false;
-
- for (int i=0; i<size; i++) m_waveData[i] = data[i];
- return true;
+ Free();
+
+ m_data = new wxSoundDataMemory(size, data);
+
+ return CheckCreatedOk();
}
bool wxSound::DoPlay(unsigned flags) const
{
- if (!IsOk())
- return false;
-
- return (::PlaySound((LPCTSTR)m_waveData, NULL,
- SND_MEMORY | SND_NODEFAULT |
- ((flags & wxSOUND_ASYNC) ? SND_ASYNC : SND_SYNC) |
- ((flags & wxSOUND_LOOP) ? (SND_LOOP | SND_ASYNC) : 0))
- != 0);
-}
+ if ( !IsOk() || !m_data->IsOk() )
+ return false;
-bool wxSound::Free()
-{
- if (m_waveData)
- {
-#ifdef __WXWINCE__
- HGLOBAL waveData = (HGLOBAL) m_waveData;
-#else
- HGLOBAL waveData = GlobalHandle(m_waveData);
-#endif
+ DWORD flagsMSW = m_data->GetSoundFlag();
+ HMODULE hmod = flagsMSW == SND_RESOURCE ? wxGetInstance() : NULL;
+
+ // we don't want replacement default sound
+ flagsMSW |= SND_NODEFAULT;
- if (waveData)
+ // NB: wxSOUND_SYNC is 0, don't test for it
+ flagsMSW |= (flags & wxSOUND_ASYNC) ? SND_ASYNC : SND_SYNC;
+ if ( flags & wxSOUND_LOOP )
{
-#ifndef __WXWINCE__
- if (m_isResource)
- ::FreeResource(waveData);
- else
-#endif
- {
- GlobalUnlock(waveData);
- GlobalFree(waveData);
- }
-
- m_waveData = NULL;
- m_waveLength = 0;
- return true;
+ // looping only works with async flag
+ flagsMSW |= SND_LOOP | SND_ASYNC;
}
- }
- return false;
+
+ return ::PlaySound(m_data->GetSoundData(), hmod, flagsMSW) != FALSE;
}
-/*static*/ void wxSound::Stop()
+/* static */
+void wxSound::Stop()
{
::PlaySound(NULL, NULL, 0);
}
#endif // wxUSE_SOUND
+