Skip to content
Browse files

Implement portaudio sound library support for linux

  • Loading branch information...
1 parent bce237a commit 25acd60accd7a61faa5659d82a7530a39eecc9fd David Register committed Dec 22, 2012
Showing with 584 additions and 18 deletions.
  1. +19 −2 CMakeLists.txt
  2. +92 −0 FindPortaudio.cmake
  3. +34 −0 data/license.txt
  4. +2 −1 include/ais.h
  5. +0 −1 include/chcanv.h
  6. +60 −0 include/navutil.h
  7. +17 −2 src/chart1.cpp
  8. +8 −5 src/chcanv.cpp
  9. +342 −0 src/navutil.cpp
  10. +10 −7 src/options.cpp
View
21 CMakeLists.txt
@@ -41,7 +41,7 @@ ENDIF (COMMAND cmake_policy)
PROJECT(OpenCPN)
-#SET(CMAKE_VERBOSE_MAKEFILE ON)
+SET(CMAKE_VERBOSE_MAKEFILE ON)
IF(APPLE)
SET(PACKAGE_NAME OpenCPN)
@@ -67,7 +67,7 @@ IF (NOT WIN32)
SET (LIB_INSTALL_DIR "lib")
IF (EXISTS /etc/debian_version)
SET (PACKAGE_FORMAT "DEB")
- SET (PACKAGE_DEPS "libc6, libwxgtk2.8-0 (>= 2.8.7.1), libglu1-mesa (>= 7.0.0), libgl1-mesa-glx (>= 7.0.0), zlib1g, bzip2, libsdl1.2debian, libtinyxml2.6.2")
+ SET (PACKAGE_DEPS "libc6, libwxgtk2.8-0 (>= 2.8.7.1), libglu1-mesa (>= 7.0.0), libgl1-mesa-glx (>= 7.0.0), zlib1g, bzip2, libsdl1.2debian, libtinyxml2.6.2, libportaudio2")
SET (PACKAGE_RECS "xcalib")
SET (LIB_INSTALL_DIR "lib")
IF (CMAKE_SIZEOF_VOID_P MATCHES "8")
@@ -212,6 +212,23 @@ IF (GTK2_FOUND)
ELSE(GTK2_FOUND)
MESSAGE (STATUS "GTK2 Not found...")
ENDIF (GTK2_FOUND)
+
+IF(UNIX)
+INCLUDE("FindPortaudio.cmake")
+IF (PORTAUDIO_FOUND)
+ MESSAGE (STATUS "Portaudio Found")
+# INCLUDE_DIRECTORIES(${PORTAUDIO_INCLUDE_DIRS})
+# SET(EXTRA_LIBS ${EXTRA_LIBS} ${PORTAUDIO_LIBRARIES})
+# ADD_DEFINITIONS(${PORTAUDIO_DEFINITIONS})
+# ADD_DEFINITIONS(-DOCPN_USE_PORTAUDIO)
+ELSE (PORTAUDIO_FOUND)
+ MESSAGE (STATUS "Portaudio Not Found...")
+ENDIF (PORTAUDIO_FOUND)
+
+#SET(EXTRA_LIBS ${EXTRA_LIBS} "/usr/lib/i386-linux-gnu/libportaudio.so.2.0.0")
+#ADD_DEFINITIONS(-DOCPN_USE_PORTAUDIO)
+ENDIF(UNIX)
+
ENDIF (NOT WIN32 AND NOT APPLE)
FIND_PACKAGE(Gettext REQUIRED)
View
92 FindPortaudio.cmake
@@ -0,0 +1,92 @@
+
+# - Try to find Portaudio
+# Once done this will define
+#
+# PORTAUDIO_FOUND - system has Portaudio
+# PORTAUDIO_INCLUDE_DIRS - the Portaudio include directory
+# PORTAUDIO_LIBRARIES - Link these to use Portaudio
+# PORTAUDIO_DEFINITIONS - Compiler switches required for using Portaudio
+#
+# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
+#
+# Redistribution and use is allowed according to the terms of the New BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+#
+
+#Redistribution and use in source and binary forms, with or without
+#modification, are permitted provided that the following conditions are met:
+#
+#* Redistributions of source code must retain the above copyright notice, this
+#list of conditions and the following disclaimer.
+#
+#* Redistributions in binary form must reproduce the above copyright notice,
+#this list of conditions and the following disclaimer in the
+#documentation and/or other materials provided with the distribution.
+#
+#* Neither the name of the CMake-Modules Project nor the names of its
+#contributors may be used to endorse or promote products derived from this
+#software without specific prior written permission.
+#
+#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+#DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+#ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+#ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+if (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS)
+# in cache already
+set(PORTAUDIO_FOUND TRUE)
+else (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS)
+find_path(PORTAUDIO_INCLUDE_DIR
+NAMES
+portaudio.h
+PATHS
+/usr/include
+/usr/local/include
+/opt/local/include
+/sw/include
+)
+
+find_library(PORTAUDIO_LIBRARY
+NAMES
+portaudio
+PATHS
+/usr/lib
+/usr/local/lib
+/opt/local/lib
+/usr/lib/i386-linux-gnu
+/sw/lib
+)
+
+set(PORTAUDIO_INCLUDE_DIRS
+${PORTAUDIO_INCLUDE_DIR}
+)
+set(PORTAUDIO_LIBRARIES
+${PORTAUDIO_LIBRARY}
+)
+
+if (PORTAUDIO_INCLUDE_DIRS AND PORTAUDIO_LIBRARIES)
+set(PORTAUDIO_FOUND TRUE)
+endif (PORTAUDIO_INCLUDE_DIRS AND PORTAUDIO_LIBRARIES)
+
+if (PORTAUDIO_FOUND)
+if (NOT Portaudio_FIND_QUIETLY)
+message(STATUS "Found Portaudio: ${PORTAUDIO_LIBRARIES}")
+endif (NOT Portaudio_FIND_QUIETLY)
+else (PORTAUDIO_FOUND)
+if (Portaudio_FIND_REQUIRED)
+message(FATAL_ERROR "Could not find Portaudio")
+endif (Portaudio_FIND_REQUIRED)
+endif (PORTAUDIO_FOUND)
+
+# show the PORTAUDIO_INCLUDE_DIRS and PORTAUDIO_LIBRARIES variables only in the advanced view
+mark_as_advanced(PORTAUDIO_INCLUDE_DIRS PORTAUDIO_LIBRARIES)
+
+endif (PORTAUDIO_LIBRARIES AND PORTAUDIO_INCLUDE_DIRS)
View
34 data/license.txt
@@ -343,3 +343,37 @@ proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
+
+
+Portions of this program are distributed under the terms of the New BSD
+License. Those portions include:
+
+FindPortaudio.cmake
+Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
+
+Redistribution and use is allowed according to the terms of the New BSD license.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+* Neither the name of the CMake-Modules Project nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
3 include/ais.h
@@ -44,6 +44,7 @@
#include "dychart.h"
#include "chart1.h"
#include "datastream.h" // For GenericPosDatEx
+#include "navutil.h"
// Constants
#ifndef PI
@@ -375,7 +376,7 @@ class AIS_Decoder : public wxEvtHandler
bool m_bAIS_Audio_Alert_On;
wxTimer m_AIS_Audio_Alert_Timer;
- wxSound m_AIS_Sound;
+ OCPN_Sound m_AIS_Sound;
int m_n_targets;
bool m_bSuppressed;
bool m_bGeneralAlert;
View
1 include/chcanv.h
@@ -554,7 +554,6 @@ class ChartCanvas: public wxWindow
double m_zoom_target_factor;
double m_zoom_current_factor;
- wxSound m_anchorwatch_sound;
DECLARE_EVENT_TABLE()
};
View
60 include/navutil.h
@@ -34,12 +34,17 @@
#include <wx/config.h>
#include <wx/confbase.h>
#include <wx/fileconf.h>
+#include <wx/sound.h>
#ifdef __WXMSW__
#include <wx/msw/regconf.h>
#include <wx/msw/iniconf.h>
#endif
+#ifdef OCPN_USE_PORTAUDIO
+#include "portaudio.h"
+#endif
+
#include "bbox.h"
#include "s52s57.h"
#include "chcanv.h"
@@ -810,4 +815,59 @@ extern "C" double vVectorSquared(pVector2D v0);
+//---------------------------------------------------------------------------------
+// OpenCPN internal Sound support class
+//---------------------------------------------------------------------------------
+
+/// Sound data, as loaded from .wav file:
+class OCPNSoundData
+{
+public:
+ OCPNSoundData() : m_dataWithHeader(NULL) {}
+ ~OCPNSoundData() {};
+
+ // .wav header information:
+ unsigned m_channels; // num of channels (mono:1, stereo:2)
+ unsigned m_samplingRate;
+ unsigned m_bitsPerSample; // if 8, then m_data contains unsigned 8bit
+ // samples (wxUint8), if 16 then signed 16bit
+ // (wxInt16)
+ unsigned m_samples; // length in samples:
+
+ // wave data:
+ size_t m_dataBytes;
+ wxUint8 *m_data; // m_dataBytes bytes of data
+
+ wxUint8 *m_dataWithHeader; // ditto, but prefixed with .wav header
+};
+
+
+
+
+class OCPN_Sound: public wxSound
+{
+public:
+ OCPN_Sound();
+ ~OCPN_Sound();
+
+ bool IsOk() const;
+ bool Create(const wxString& fileName, bool isResource = false);
+ bool Play(unsigned flags = wxSOUND_ASYNC) const;
+ bool IsPlaying() const;
+ void Stop();
+
+private:
+ bool m_OK;
+
+#ifdef OCPN_USE_PORTAUDIO
+ bool LoadWAV(const wxUint8 *data, size_t length, bool copyData);
+ void FreeMem(void);
+
+ OCPNSoundData *m_osdata;
+ PaStream *m_stream;
+#endif
+
+};
+
+
#endif
View
19 src/chart1.cpp
@@ -111,6 +111,10 @@
#include <wx/jsonreader.h>
+#ifdef OCPN_USE_PORTAUDIO
+#include "portaudio.h"
+#endif
+
WX_DECLARE_OBJARRAY(wxDialog *, MyDialogPtrArray);
#include <wx/arrimpl.cpp>
@@ -222,7 +226,9 @@ wxArrayOfConnPrm *g_pConnectionParams;
wxDateTime g_start_time;
wxDateTime g_loglast_time;
-wxSound bells_sound[8];
+OCPN_Sound bells_sound[8];
+
+OCPN_Sound g_anchorwatch_sound;
RoutePoint *pAnchorWatchPoint1;
RoutePoint *pAnchorWatchPoint2;
@@ -582,6 +588,8 @@ char bells_sound_file_name[8][12] = // pjotrc 2010.02.09
};
+int portaudio_initialized;
+
static char nmea_tick_chars[] = { '|', '/', '-', '\\', '|', '/', '-', '\\' };
static int tick_idx;
@@ -761,6 +769,9 @@ bool MyApp::OnInit()
{
if( !wxApp::OnInit() ) return false;
+// bells_sound[0].Create(_T("/home/dsr/2bells.wav"));
+// bells_sound[0].Play();
+
g_pPlatform = new wxPlatformInfo;
// On MSW, force the entire process to run on one CPU core only
@@ -1994,7 +2005,11 @@ int MyApp::OnExit()
#endif
#endif
-// _CrtDumpMemoryLeaks( );
+#ifdef OCPN_USE_PORTAUDIO
+ if(portaudio_initialized)
+ Pa_Terminate();
+#endif
+
// Restore any changed system colors
#ifdef __WXMSW__
View
13 src/chcanv.cpp
@@ -271,6 +271,8 @@ extern ocpnStyle::StyleManager* g_StyleManager;
extern Multiplexer *g_pMUX;
extern wxArrayOfConnPrm *g_pConnectionParams;
+extern OCPN_Sound g_anchorwatch_sound;
+
// TODO why are these static?
static int mouse_x;
static int mouse_y;
@@ -6680,17 +6682,18 @@ void ChartCanvas::AlertDraw( ocpnDC& dc )
} else
AnchorAlertOn2 = false;
+
if( play_sound ) {
- if( !m_anchorwatch_sound.IsOk() ) m_anchorwatch_sound.Create( g_sAIS_Alert_Sound_File );
+ if( !g_anchorwatch_sound.IsOk() ) g_anchorwatch_sound.Create( g_sAIS_Alert_Sound_File );
#ifndef __WXMSW__
- if(m_anchorwatch_sound.IsOk() && !m_anchorwatch_sound.IsPlaying())
- m_anchorwatch_sound.Play();
+ if(g_anchorwatch_sound.IsOk() && !g_anchorwatch_sound.IsPlaying())
+ g_anchorwatch_sound.Play();
#else
- if( m_anchorwatch_sound.IsOk() ) m_anchorwatch_sound.Play();
+ if( g_anchorwatch_sound.IsOk() ) g_anchorwatch_sound.Play();
#endif
} else {
- if( m_anchorwatch_sound.IsOk() ) m_anchorwatch_sound.Stop();
+ if( g_anchorwatch_sound.IsOk() ) g_anchorwatch_sound.Stop();
}
}
View
342 src/navutil.cpp
@@ -308,6 +308,7 @@ extern ocpnStyle::StyleManager* g_StyleManager;
extern wxArrayString TideCurrentDataSet;
extern wxString g_TCData_Dir;
extern Multiplexer *g_pMUX;
+extern bool portaudio_initialized;
//------------------------------------------------------------------------------
// Some wxWidgets macros for useful classes
@@ -8121,3 +8122,344 @@ void TTYWindow::Add( wxString &line )
if( m_pScroll ) m_pScroll->Add( line );
}
+
+//---------------------------------------------------------------------------------
+// OpenCPN internal Sound support class
+//---------------------------------------------------------------------------------
+
+#ifdef OCPN_USE_PORTAUDIO
+
+// Static variables associated with portaudio library
+
+PaStream *stream;
+void *sdata;
+int sindex;
+int smax_samples;
+bool splaying;
+
+/* This routine will be called by the PortAudio engine when audio is needed.
+ * It may called at interrupt level on some machines so don't do anything
+ * that could mess up the system like calling malloc() or free().
+ */
+static int OCPNSoundCallback( const void *inputBuffer, void *outputBuffer,
+ unsigned long framesPerBuffer,
+ const PaStreamCallbackTimeInfo* timeInfo,
+ PaStreamCallbackFlags statusFlags,
+ void *userData )
+{
+ /* Cast data passed through stream to our structure. */
+ wxUint16 *data = (wxUint16 *)userData;
+ wxUint16 *out = (wxUint16*)outputBuffer;
+ unsigned int i;
+ bool bdone = false;
+ (void) inputBuffer; /* Prevent unused variable warning. */
+ for( i=0; i<framesPerBuffer; i++ )
+ {
+ *out = data[sindex];
+ out++;
+ sindex++;
+
+ if( sindex >= smax_samples ) {
+ bdone = true;
+ break;
+ }
+ }
+
+ if(bdone)
+ return paComplete;
+ else
+ return 0;
+}
+
+static void OCPNSoundFinishedCallback( void *userData )
+{
+ splaying = false;
+}
+
+
+OCPN_Sound::OCPN_Sound()
+{
+ if(!portaudio_initialized) {
+ PaError err = Pa_Initialize();
+ if( err != paNoError ) {
+ printf( "PortAudio CTOR error: %s\n", Pa_GetErrorText( err ) );
+ }
+ portaudio_initialized = true;
+ }
+
+ m_osdata = NULL;
+ m_OK = false;
+ m_stream = NULL;
+
+}
+
+OCPN_Sound::~OCPN_Sound()
+{
+ if( m_stream ) {
+ Pa_CloseStream( m_stream );
+ }
+
+ FreeMem();
+}
+
+bool OCPN_Sound::IsOk() const
+{
+ return m_OK;
+}
+
+bool OCPN_Sound::Create(const wxString& fileName, bool isResource)
+{
+ m_OK = false;
+
+ FreeMem();
+
+ wxFile fileWave;
+ if (!fileWave.Open(fileName, wxFile::read))
+ {
+ return false;
+ }
+
+ wxFileOffset lenOrig = fileWave.Length();
+ if ( lenOrig == wxInvalidOffset )
+ return false;
+
+ size_t len = wx_truncate_cast(size_t, lenOrig);
+ wxUint8 *data = new wxUint8[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, true))
+ {
+ delete [] data;
+ wxLogError(_("Sound file '%s' is in unsupported format."),
+ fileName.c_str());
+ return false;
+ }
+
+ sdata = m_osdata->m_data; //The raw sound data
+ sindex = 0;
+ smax_samples = m_osdata->m_samples;
+
+ PaError err;
+ m_stream = NULL;
+
+ /* Open an audio I/O stream. */
+ err = Pa_OpenDefaultStream( &m_stream,
+ 0, /* no input channels */
+ m_osdata->m_channels,
+ paInt16,
+ m_osdata->m_samplingRate,
+ 256, /* frames per buffer, i.e. the number
+ of sample frames that PortAudio will
+ request from the callback. Many apps
+ may want to use
+ paFramesPerBufferUnspecified, which
+ tells PortAudio to pick the best,
+ possibly changing, buffer size.*/
+ OCPNSoundCallback, /* this is your callback function */
+ sdata ); /*This is a pointer that will be passed to
+ your callback*/
+ if( err != paNoError )
+ printf( "PortAudio Create() error: %s\n", Pa_GetErrorText( err ) );
+
+ err = Pa_SetStreamFinishedCallback( m_stream, OCPNSoundFinishedCallback );
+ if( err != paNoError )
+ printf( "PortAudio SetStreamFinishedCallback() error: %s\n", Pa_GetErrorText( err ) );
+
+ m_OK = true;
+
+ return true;
+}
+
+bool OCPN_Sound::Play(unsigned flags) const
+{
+ if(m_stream) {
+ Pa_StopStream( m_stream );
+
+ if( !splaying ) {
+ sdata = m_osdata->m_data; //The raw sound data
+ sindex = 0;
+ smax_samples = m_osdata->m_samples;
+ stream = m_stream;
+
+ PaError err = Pa_StartStream( stream );
+ if( err != paNoError ) {
+ printf( "PortAudio Play() error: %s\n", Pa_GetErrorText( err ) );
+ return false;
+ }
+ else {
+ splaying = true;
+ return true;
+ }
+
+ }
+ else
+ return false;
+ }
+ return false;
+}
+
+bool OCPN_Sound::IsPlaying() const
+{
+ return splaying;
+}
+
+void OCPN_Sound::Stop()
+{
+ Pa_StopStream( m_stream );
+ splaying = false;
+
+}
+
+typedef struct
+{
+ wxUint32 uiSize;
+ wxUint16 uiFormatTag;
+ wxUint16 uiChannels;
+ wxUint32 ulSamplesPerSec;
+ wxUint32 ulAvgBytesPerSec;
+ wxUint16 uiBlockAlign;
+ wxUint16 uiBitsPerSample;
+} WAVEFORMAT;
+
+#define WAVE_FORMAT_PCM 1
+#define WAVE_INDEX 8
+#define FMT_INDEX 12
+
+bool OCPN_Sound::LoadWAV(const wxUint8 *data, size_t length, bool copyData)
+{
+ // 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;
+
+ 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);
+ waveformat.uiChannels = wxUINT16_SWAP_ON_BE(waveformat.uiChannels);
+ waveformat.ulSamplesPerSec = wxUINT32_SWAP_ON_BE(waveformat.ulSamplesPerSec);
+ waveformat.ulAvgBytesPerSec = wxUINT32_SWAP_ON_BE(waveformat.ulAvgBytesPerSec);
+ 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)
+ return false;
+ if (memcmp(&data[FMT_INDEX], "fmt ", 4) != 0)
+ return false;
+ if (memcmp(&data[FMT_INDEX + waveformat.uiSize + 8], "data", 4) != 0)
+ return false;
+
+ if (waveformat.uiFormatTag != WAVE_FORMAT_PCM)
+ return false;
+
+ if (waveformat.ulSamplesPerSec !=
+ waveformat.ulAvgBytesPerSec / waveformat.uiBlockAlign)
+ return false;
+
+ m_osdata = new OCPNSoundData;
+ m_osdata->m_dataWithHeader = NULL;
+ m_osdata->m_channels = waveformat.uiChannels;
+ m_osdata->m_samplingRate = waveformat.ulSamplesPerSec;
+ m_osdata->m_bitsPerSample = waveformat.uiBitsPerSample;
+ m_osdata->m_samples = ul / (m_osdata->m_channels * m_osdata->m_bitsPerSample / 8);
+ m_osdata->m_dataBytes = ul;
+
+ if (copyData)
+ {
+ m_osdata->m_dataWithHeader = new wxUint8[length];
+ memcpy(m_osdata->m_dataWithHeader, data, length);
+ }
+ else
+ m_osdata->m_dataWithHeader = (wxUint8*)data;
+
+ m_osdata->m_data =
+ (&m_osdata->m_dataWithHeader[FMT_INDEX + waveformat.uiSize + 8]);
+
+ return true;
+}
+
+void OCPN_Sound::FreeMem(void)
+{
+ if( m_osdata ) {
+ if( m_osdata->m_dataWithHeader )
+ delete [] m_osdata->m_dataWithHeader;
+ delete m_osdata;
+
+ m_osdata = NULL;
+ }
+}
+
+#else //OCPN_USE_PORTAUDIO
+OCPN_Sound::OCPN_Sound()
+{
+// wxSound::wxSound();
+}
+
+OCPN_Sound::~OCPN_Sound()
+{
+}
+
+bool OCPN_Sound::IsOk() const
+{
+ return wxSound::IsOk();
+}
+
+bool OCPN_Sound::Create(const wxString& fileName, bool isResource)
+{
+ return wxSound::Create(fileName, isResource);
+}
+
+bool OCPN_Sound::Play(unsigned flags) const
+{
+ return wxSound::Play(flags);
+}
+
+bool OCPN_Sound::IsPlaying() const
+{
+#ifndef __WXMSW__
+ return wxSound::IsPlaying();
+#else
+ return false;
+#endif
+}
+
+void OCPN_Sound::Stop()
+{
+ wxSound::Stop();
+}
+
+
+#endif //OCPN_USE_PORTAUDIO
View
17 src/options.cpp
@@ -2995,18 +2995,21 @@ void options::OnButtonSelectSound( wxCommandEvent& event )
void options::OnButtonTestSound( wxCommandEvent& event )
{
-#if wxUSE_LIBSDL
-// printf("wxUSE_LIBSDL true\n");
-#endif
- wxSound AIS_Sound( g_sAIS_Alert_Sound_File );
+ OCPN_Sound AIS_Sound;
+ AIS_Sound.Create( g_sAIS_Alert_Sound_File );
if( AIS_Sound.IsOk() ) {
-// printf("playing sound\n");
AIS_Sound.Play();
+
+ int t = 0;
+ while( AIS_Sound.IsPlaying() && (t < 10) ) {
+ wxSleep(1);
+ t++;
+ }
+ if( AIS_Sound.IsPlaying() )
+ AIS_Sound.Stop();
}
-// else
-// printf("sound is NOT ok\n");
}

0 comments on commit 25acd60

Please sign in to comment.
Something went wrong with that request. Please try again.