[gimp-gap] added portable audioplayback support.



commit 393caed73fb930b347625fe379cc8cd92322fde2
Author: Wolfgang Hofer <wolfgangh svn gnome org>
Date:   Sat Feb 9 19:55:54 2013 +0100

    added portable audioplayback support.

 ChangeLog                 |   33 ++
 Makefile.am               |    2 +-
 configure.in              |   82 ++++-
 gap/Makefile.am           |   20 +-
 gap/gap_apcl_lib.h        |  129 +++++++
 gap/gap_player_dialog.c   |   69 ++--
 gap/gap_sdl_audioplayer.c |  933 +++++++++++++++++++++++++++++++++++++++++++++
 gap/gap_sdl_audioplayer.h |  129 +++++++
 8 files changed, 1348 insertions(+), 49 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 36ac2a0..abd20d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2013-02-10 Wolfgang Hofer <hof gimp org>
+
+- added audio support for other Operating Systems than Linux.
+  Audio playback now can be configured to use an SDL media library based
+  audio playback module (as alternative to the already existing
+  wavplay client/server based audio playback).
+
+  The configure option --disable-audio-support was removed and
+  replaced by the new options: 
+
+     --disable-audio-support-sdl
+     --disable-audio-support-wavplay  
+
+  on Linux
+    enable-audio-support-sdl is default
+    enable-audio-support-wavplay  is fallback (when SDL library is not installed)
+
+  on Windows
+    enable-audio-support-sdl is default,
+    
+    NO audio playback possible when SDL library  library is not installed)
+    
+
+  The SDL library is available for Linux, Windows and MacOS
+
+
+    * configure.in
+    * Makefile.am
+    * gap/Makefile.am
+    * gap/gap_apcl_lib.h              #new file
+    * gap/gap_sdl_audioplayer.c [.h]  #new files
+    * gap/gap_player_dialog.c
+
 2013-01-16 Wolfgang Hofer <hof gimp org>
 
 - fixed bug in the storybard master properties that truncated framerate to integer values.
diff --git a/Makefile.am b/Makefile.am
index 561ac5b..42d1dac 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 
-if GAP_AUDIO_SUPPORT
+if GAP_AUDIO_SUPPORT_WAVPLAY
 LIBWAVCLIENT=libwavplayclient
 endif
 
diff --git a/configure.in b/configure.in
index be9211e..b977c35 100644
--- a/configure.in
+++ b/configure.in
@@ -1085,30 +1085,88 @@ AC_SUBST(GAPVIDEOAPI_EXTINCS)
 
 
 dnl Test for audiosupport
-dnl audiosupport currently is based on wavplay that is available on UNIX systems
-dnl (the wavplay client does not compile on Windows)
+dnl First check for the SDL media library and configure to compile and link
+dnl with the SDL based audioplayer when present.
+dnl (the check for libsdl uses the SDL specific sdl-config when available
+dnl  and uses pkg-config as alternative check when sdl-config was not found.)
 dnl ------------------------
-AC_ARG_ENABLE(audio_support,
-              [  --disable-audio-support      don't build with audio support])
+sdl_audio_err=""
+SDL_CONFIG="sdl-config"
+GAP_AUDIO_SDL_LIBS=""
+GAP_AUDIO_SDL_CFLAGS=""
+AC_ARG_ENABLE(audio_support_sdl,
+              [  --disable-audio-support-sdl      don't build with SDL based audio support])
+  if test "x$enable_audio_support_sdl" != "xno"; then
+
+dnl  -- TODO the AC_CHECK_HEADER  for SDL_audio.h seems not to work 
+dnl    (e.g failed in my development environment even when SDL_audio.h is present
+dnl    at the rellevant directory (that both  pkg-config --cflags sdl    AND sdl-config --cflags 
+dnl    gives as result) 
+dnl    -- therefore skip the check for SDL_audio.h 
+dnl
+dnl
+dnl      AC_CHECK_LIB(SDL, SDL_OpenAudio,
+dnl        [AC_CHECK_HEADER(SDL_audio.h,
+dnl          sdl_audio_err="",
+dnl          sdl_audio_err="$NEW_LINE SDL audio header file (SDL_audio.h) not found (audio playback will be disabled)")],
+dnl        sdl_audio_err="SDL library (libsdl) not found (audio playback will be disabled)")
+
+      AC_CHECK_LIB(SDL, SDL_OpenAudio,
+        sdl_audio_err="",
+        sdl_audio_err="SDL library (libsdl) not found (audio playback will be disabled)")
+        
+      if test "x$sdl_audio_err" != "x"; then
+        enable_audio_support_sdl="no"
+      else
+        enable_audio_support_sdl="yes"
+        AC_CHECK_PROG(SDL_CONFIG, "$SDL_CONFIG", yes, no)
+        if test $SDL_CONFIG = no; then
+          GAP_AUDIO_SDL_CFLAGS=`$PKG_CONFIG --cflags sdl`
+          GAP_AUDIO_SDL_LIBS=`$PKG_CONFIG --libs sdl`
+        else
+          GAP_AUDIO_SDL_CFLAGS=`$SDL_CONFIG --cflags`
+          GAP_AUDIO_SDL_LIBS=`$SDL_CONFIG --libs`
+        fi
+
+        AC_DEFINE(GAP_ENABLE_AUDIO_SUPPORT_SDL, 1,
+              [Define to 1 to enable audio support via SDL media library])
+      fi
+  fi
+
+AM_CONDITIONAL(GAP_AUDIO_SUPPORT_SDL, test "x$enable_audio_support_sdl" != "xno")
+AC_SUBST(GAP_AUDIO_SDL_CFLAGS)
+AC_SUBST(GAP_AUDIO_SDL_LIBS)
+
+
+dnl further checks for alternative audiosupport, based on wavplay client-server that is available on UNIX systems
+dnl (note that the wavplay client does not compile on Windows)
+dnl ------------------------
+AC_ARG_ENABLE(audio_support_wavplay,
+              [  --disable-audio-support-wavplay      don't build with wavplay based audio support])
   if test "x$os_win32" = "xyes"; then
-     enable_audio_support=no
+     enable_audio_support_wavplay=no
+  fi
+  if test "x$enable_audio_support_sdl" != "xno"; then
+     if test "x$enable_audio_support_sdl" != "x"; then
+        enable_audio_support_wavplay=no
+     fi;
   fi
 
-  if test "x$enable_audio_support" != "xno"; then
+  if test "x$enable_audio_support_wavplay" != "xno"; then
     AC_CHECK_PROG(WAVPLAY_SERVER, wavplay, yes, no)
       if test $WAVPLAY_SERVER = no; then
         audio_warning="
-Audio support will be compiled in but will not work because the wavplay
-executable was not found. For audio support the wavplay audioserver must
+Audio support based on wavplay client-server implementation will be compiled but will not work because the wavplay
+executable was not found. For this kind of audio support the wavplay audioserver must
 be installed at runtime.
 "
       fi
 
-    AC_DEFINE(GAP_ENABLE_AUDIO_SUPPORT, 1,
-              [Define to 1 to enable audio support])
+    AC_DEFINE(GAP_ENABLE_AUDIO_SUPPORT_WAVPLAY, 1,
+              [Define to 1 to enable audio support via wavplay client])
   fi
 
-AM_CONDITIONAL(GAP_AUDIO_SUPPORT, test "x$enable_audio_support" != "xno")
+AM_CONDITIONAL(GAP_AUDIO_SUPPORT_WAVPLAY, test "x$enable_audio_support_wavplay" != "xno")
 
 dnl optional compile preview widget with GDK-pixbuf support
 dnl 
@@ -1221,4 +1279,4 @@ docs/reference/Makefile
 docs/reference/txt/Makefile
 ])
 
-AC_MSG_RESULT($frontends_warning $audio_warning $videoapi_warning $moved_old_ffmpeg_warn $moved_old_libmpeg3_warn $vid_ffmpeg_warning $yasm_warn $vid_mpeg3_warning $vid_quicktime_warning $vid_xvidcore_warning $pkg_cfg_warning)
+AC_MSG_RESULT($frontends_warning $sdl_audio_err $audio_warning $videoapi_warning $moved_old_ffmpeg_warn $moved_old_libmpeg3_warn $vid_ffmpeg_warning $yasm_warn $vid_mpeg3_warning $vid_quicktime_warning $vid_xvidcore_warning $pkg_cfg_warning)
diff --git a/gap/Makefile.am b/gap/Makefile.am
index 1173ccc..058948b 100644
--- a/gap/Makefile.am
+++ b/gap/Makefile.am
@@ -12,10 +12,16 @@ endif
 
 GAP_DECODE_MPLAYER_FRONTEND = gap_decode_mplayer
 
-if GAP_AUDIO_SUPPORT
-WAVPLAYCLIENT = $(top_builddir)/libwavplayclient/libwavplayclient.a
+if GAP_AUDIO_SUPPORT_WAVPLAY
+GAP_AUDIO_LIBS = $(top_builddir)/libwavplayclient/libwavplayclient.a
 endif
 
+if GAP_AUDIO_SUPPORT_SDL
+GAP_SDL_AUDIO_EXTRASRC = gap_sdl_audioplayer.h gap_sdl_audioplayer.c
+GAP_AUDIO_LIBS = $(GAP_AUDIO_SDL_LIBS)
+endif
+
+
 if GAP_VIDEOAPI_SUPPORT
 GAPVIDEOAPI = $(top_builddir)/libgapvidapi/libgapvidapi.a  $(GAPVIDEOAPI_EXTLIBS)
 INC_GAPVIDEOAPI = -I$(top_srcdir)/libgapvidapi $(GAPVIDEOAPI_EXTINCS)
@@ -339,6 +345,7 @@ gap_player_SOURCES = \
 	gap_player_dialog.h	\
 	gap_player_cache.c	\
 	gap_player_cache.h	\
+	$(GAP_SDL_AUDIO_EXTRASRC) \
 	gap_audio_extract.c	\
 	gap_audio_extract.h	\
 	gap_drawable_vref_parasite.c	\
@@ -379,6 +386,7 @@ gap_storyboard_SOURCES = \
 	gap_player_dialog.h	\
 	gap_player_cache.c	\
 	gap_player_cache.h	\
+	$(GAP_SDL_AUDIO_EXTRASRC) \
 	gap_drawable_vref_parasite.c	\
 	gap_drawable_vref_parasite.h	\
 	gap_libgapstory.h	\
@@ -400,6 +408,7 @@ gap_video_extract_SOURCES = \
 	gap_player_dialog.h	\
 	gap_player_cache.c	\
 	gap_player_cache.h	\
+	$(GAP_SDL_AUDIO_EXTRASRC) \
 	gap_drawable_vref_parasite.c	\
 	gap_drawable_vref_parasite.h	\
 	gap_libgapstory.h	\
@@ -488,6 +497,7 @@ INCLUDES = \
 	-I$(top_srcdir)/libwavplayclient	\
 	$(INC_LIBGAPBASE)	\
 	$(INC_GAPVIDEOAPI)	\
+	$(GAP_AUDIO_SDL_CFLAGS)	\
 	$(GIMP_CFLAGS)	\
 	-I$(includedir)
 
@@ -511,10 +521,10 @@ gap_decode_mplayer_LDADD =   $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
 gap_morph_LDADD =            $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS) -lm
 gap_name2layer_LDADD =       $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
 gap_navigator_dialog_LDADD = $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
-gap_player_LDADD =           $(GAPVIDEOAPI) $(WAVPLAYCLIENT) ${LIBGAPSTORY} $(LIBGAPBASE) $(GIMP_LIBS)
+gap_player_LDADD =           $(GAPVIDEOAPI) $(GAP_AUDIO_LIBS) ${LIBGAPSTORY} $(LIBGAPBASE) $(GIMP_LIBS)
 gap_onion_LDADD =            $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
-gap_storyboard_LDADD =       $(GAPVIDEOAPI) $(WAVPLAYCLIENT) ${LIBGAPSTORY} $(LIBGAPBASE) $(GIMP_LIBS)
-gap_video_extract_LDADD =    $(GAPVIDEOAPI) $(WAVPLAYCLIENT) ${LIBGAPSTORY} $(LIBGAPBASE) $(GIMP_LIBS)
+gap_storyboard_LDADD =       $(GAPVIDEOAPI) $(GAP_AUDIO_LIBS) ${LIBGAPSTORY} $(LIBGAPBASE) $(GIMP_LIBS)
+gap_video_extract_LDADD =    $(GAPVIDEOAPI) $(GAP_AUDIO_LIBS) ${LIBGAPSTORY} $(LIBGAPBASE) $(GIMP_LIBS)
 gap_video_index_LDADD =      $(GAPVIDEOAPI) $(LIBGAPSTORY) $(LIBGAPBASE)  $(GIMP_LIBS)
 gap_fg_matting_LDADD =       $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS) -lm
 gap_fire_pattern_LDADD =     $(LIBGIMPGAP)  $(LIBGAPBASE) $(GIMP_LIBS)
diff --git a/gap/gap_apcl_lib.h b/gap/gap_apcl_lib.h
new file mode 100644
index 0000000..3b5d2af
--- /dev/null
+++ b/gap/gap_apcl_lib.h
@@ -0,0 +1,129 @@
+/* gap_apcl_lib.h
+ *   Provides the GAP Audio Player Client support API functions.
+ *
+ * This module includes the relevant audio playback
+ * implementation which is configured at compiletime.
+ *
+ * following implementations are available:
+ * - SDL media library based audioplayback        GAP_ENABLE_AUDIO_SUPPORT_SDL
+ * - wavplay client/server based audioplayback    GAP_ENABLE_AUDIO_SUPPORT_WAVPLAY
+ */
+
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _GAP_APCL_LIB_H
+#define _GAP_APCL_LIB_H
+
+#define WPC_FLAGS_BITS_SIGNED_LITTLE_ENDIAN_SAMPLE     0
+#define WPC_FLAGS_BITS_UNSIGNED_LITTLE_ENDIAN_SAMPLE   1
+#define WPC_FLAGS_BITS_SIGNED_BIG_ENDIAN_SAMPLES       2
+#define WPC_FLAGS_BITS_UNSIGNED_BIG_ENDIAN_SAMPLE      3
+
+
+#ifdef GAP_ENABLE_AUDIO_SUPPORT_SDL
+#define GAP_ENABLE_AUDIO_SUPPORT 1
+/* ------- START SDL based stuff ----------------------------------------------------------- */
+
+/* use audio playback based on the SDL media library
+ * (SDL works on multiple Operating systems including Linux and Windows and McOS)
+ *
+ * AudioPlayerCLient Wrapper Procedures
+ * Implementation for SDL based audio player
+ * can use MACRO definitions for most Procedures
+ */
+
+#include <gap_sdl_audioplayer.h>
+
+#define APCL_ErrFunc GapSdlErrFunc
+
+static int apcl_have_memory_playback(void) { return (1); }
+
+/* Define MACROs to map the API functions ( apcl_* ) to SDL based player functions (gap_sdl_*) */
+#define apcl_memory_buffer(buffer,len,erf) gap_sdl_memory_buffer(buffer,len,erf) /* Tell audio_player a buffer with PCM audiodata */
+#define apcl_channels(flags,erf,channels) gap_sdl_channels(flags,erf,channels)   /*  Tell audio_player the number of channels */
+#define apcl_bits(flags,erf,bits) gap_sdl_bits(flags,erf,bits)                   /*  Tell audio_player the number of bits per sample */
+#define apcl_volume(volume,flags,erf) gap_sdl_volume(volume,flags,erf)           /*  Tell audio_player the mixvolume 0.0 to 1.0 */
+
+#define apcl_bye(flags,erf) gap_sdl_cmd(GAP_SDL_CMD_Bye,flags,erf)	/* Tell audio_player to exit */
+#define apcl_play(flags,erf) gap_sdl_cmd(GAP_SDL_CMD_Play,flags,erf)	/* Tell audio_player to play */
+#define apcl_pause(flags,erf) gap_sdl_cmd(GAP_SDL_CMD_Pause,flags,erf) /* Tell audio_player to pause */
+#define apcl_stop(flags,erf) gap_sdl_cmd(GAP_SDL_CMD_Stop,flags,erf)	/* Tell audio_player to stop */
+#define apcl_restore(flags,erf) gap_sdl_cmd(GAP_SDL_CMD_Restore,flags,erf) /* Tell audio_player to restore settings */
+#define apcl_semreset(flags,erf) gap_sdl_cmd(GAP_SDL_CMD_SemReset,flags,erf) /* No operation (audio_player has no semaphores) */
+
+#define apcl_start(erf) gap_sdl_start(erf)  /* Tell audio_player to init a playback thread */
+#define apcl_path(path,flags,erf) gap_sdl_path(path,flags,erf)	                   /* Tell audio_player a pathname */
+#define apcl_sampling_rate(rate,flags,erf) gap_sdl_sampling_rate(flags,erf,rate)  /* Tell audio_player the samplingrate */
+#define apcl_start_sample(offs,flags,erf) gap_sdl_start_sample(flags,erf,offs)    /* Tell audio_player where to start playback */
+
+
+
+/* ------- END SDL based stuff ----------------------------------------------------------- */
+
+#else
+#ifdef GAP_ENABLE_AUDIO_SUPPORT_WAVPLAY
+#define GAP_ENABLE_AUDIO_SUPPORT 1
+
+/* ------- START waveplay client/server based stuff ----------------------------------------------------------- */
+/* use wavplay as external audio server (available for Linux) */
+
+#include <wavplay.h>
+#include <wavfile.h>
+#include <client.h>
+
+
+/* AudioPlayerCLient Wrapper Procedures
+ * Implementation for wavplay client
+ * can use MACRO definitions for most Procedures
+ * -- Note that this requires the wavplay server (available on Linux) installed
+ * -- for working audio support at run time.
+ */
+
+
+#define APCL_ErrFunc ErrFunc
+
+/* static dummy implementations for (newer) features that are NOT supported by wavplay */
+static  int apcl_have_memory_playback(void) { return (0); }
+static  int apcl_bits(int flags, PCL_ErrFunc erf,int bits) { return (1); }
+static  int apcl_memory_buffer(char *buffer, long buffer_len, PCL_ErrFunc erf)  { return (1); }
+static  int apcl_channels(int flags, PCL_ErrFunc erf, int channels) { return (1); }
+
+/* apcl_volume: volume must be a value between 0.0 and 1.0 */
+extern int   apcl_volume(double volume, int flags,APCL_ErrFunc erf);
+
+/* Define MACROs to map the API functions ( apcl_* ) to wavplay client library functions (tosvr_*) */
+#define apcl_bye(flags,erf) tosvr_cmd(ToSvr_Bye,flags,erf)	/* Tell server to exit */
+#define apcl_play(flags,erf) tosvr_cmd(ToSvr_Play,flags,erf)	/* Tell server to play */
+#define apcl_pause(flags,erf) tosvr_cmd(ToSvr_Pause,flags,erf) /* Tell server to pause */
+#define apcl_stop(flags,erf) tosvr_cmd(ToSvr_Stop,flags,erf)	/* Tell server to stop */
+#define apcl_restore(flags,erf) tosvr_cmd(ToSvr_Restore,flags,erf) /* Tell server to restore settings */
+#define apcl_semreset(flags,erf) tosvr_cmd(ToSvr_SemReset,flags,erf) /* Tell server to reset semaphores */
+
+#define apcl_start(erf) tosvr_start(erf)
+#define apcl_path(path,flags,erf) tosvr_path(path,flags,erf)	/* Tell server a pathname */
+#define apcl_sampling_rate(rate,flags,erf) tosvr_sampling_rate(flags,erf,rate)	/* Tell server a pathname */
+#define apcl_start_sample(offs,flags,erf) tosvr_start_sample(flags,erf,offs)	/* Tell server a pathname */
+
+
+
+
+/* ------- END waveplay client/server based stuff ----------------------------------------------------------- */
+
+#endif  /* GAP_ENABLE_AUDIO_SUPPORT_WAVPLAY */
+#endif  /* GAP_ENABLE_AUDIO_SUPPORT_SDL */
+#endif  /* _GAP_APCL_LIB_H */
diff --git a/gap/gap_player_dialog.c b/gap/gap_player_dialog.c
index 25bc2ce..319d3d9 100644
--- a/gap/gap_player_dialog.c
+++ b/gap/gap_player_dialog.c
@@ -113,15 +113,17 @@
 #include "gap_audio_extract.h"
 #include "gap_drawable_vref_parasite.h"
 #include "gap_detail_tracking_exec.h"
+#include "gap_audio_wav.h"
 
 #include "gap-intl.h"
 
 extern int gap_debug;  /* 1 == print debug infos , 0 dont print debug infos */
 int cmdopt_x = 0;                               /* Debug option flag for wavplay */
 
-#ifdef GAP_ENABLE_AUDIO_SUPPORT
+#include "gap_apcl_lib.h"   /* headerfile for libwavplayclient (preferred) */
+
+#ifdef GAP_ENABLE_AUDIO_SUPPORT_WAVPLAY
 
-#include "wpc_lib.h"   /* headerfile for libwavplayclient (preferred) */
 
 char *env_WAVPLAYPATH = WAVPLAYPATH;            /* Default pathname of executable /usr/local/bin/wavplay */
 char *env_AUDIODEV = AUDIODEV;                  /* Default compiled in audio device */
@@ -726,13 +728,12 @@ static void
 p_audio_filename_changed(GapPlayerMainGlobalParams *gpp)
 {
 #ifdef GAP_ENABLE_AUDIO_SUPPORT
-  int fd;
   int rc;
-  int channels;                         /* Channels recorded in this wav file */
-  u_long samplerate;                    /* Sampling rate */
-  int sample_bits;                      /* data bit size (8/12/16) */
-  u_long samples;                       /* The number of samples in this file */
-  u_long datastart;                     /* The offset to the wav data */
+  long samplerate;                   /* Sampling rate in Hz */
+  long channels;                     /* Channels recorded in this wav file */
+  long bytes_per_sample;             /* data bit size (8/12/16) */
+  long sample_bits;                  /* data bit size of one sample value (8/12/16) */
+  long samples;                      /* The number of samples in this file */
 
   if (gap_debug)
   {
@@ -741,21 +742,8 @@ p_audio_filename_changed(GapPlayerMainGlobalParams *gpp)
   p_audio_stop(gpp);
   gpp->audio_status = MIN(gpp->audio_status, GAP_PLAYER_MAIN_AUSTAT_SERVER_STARTED);
 
-  /* Open the file for reading: */
-  if ( (fd = g_open(gpp->audio_filename,O_RDONLY)) < 0 )
-  {
-     p_print_and_clear_audiolabels(gpp);
-     return;
-  }
-
-  rc = WaveReadHeader(fd
-                   ,&channels
-                   ,&samplerate
-                   ,&sample_bits
-                   ,&samples
-                   ,&datastart
-                   ,p_audio_errfunc);
-  close(fd);
+  rc = gap_audio_wav_file_check(gpp->audio_filename, &samplerate, &channels
+                           , &bytes_per_sample, &sample_bits, &samples);
 
   if(rc != 0)
   {
@@ -1051,23 +1039,23 @@ p_audio_start_play(GapPlayerMainGlobalParams *gpp)
   && (flt_samplerate >= GAP_PLAYER_MAIN_MIN_SAMPLERATE)
   )
   {
-    UInt32  lu_samplerate;
+    guint32  lu_samplerate;
 
     p_audio_init(gpp);  /* tell ausioserver to go standby for this audiofile */
     gpp->audio_required_samplerate = (guint32)flt_samplerate;
     if(flt_samplerate > GAP_PLAYER_MAIN_MAX_SAMPLERATE)
     {
-      lu_samplerate = (UInt32)GAP_PLAYER_MAIN_MAX_SAMPLERATE;
+      lu_samplerate = (guint32)GAP_PLAYER_MAIN_MAX_SAMPLERATE;
       /* required samplerate is faster than highest possible audioplayback speed
        * (the audioplayback will be played but runs out of sync and cant follow)
        */
     }
     else
     {
-      lu_samplerate = (UInt32)flt_samplerate;
+      lu_samplerate = (guint32)flt_samplerate;
     }
     apcl_sampling_rate(lu_samplerate,0,p_audio_errfunc);
-    apcl_start_sample((UInt32)offset_start_samples,0,p_audio_errfunc);
+    apcl_start_sample((guint32)offset_start_samples,0,p_audio_errfunc);
     apcl_play(0,p_audio_errfunc);  /* Tell server to play */
     apcl_volume(gpp->audio_volume, 0, p_audio_errfunc);
 
@@ -1082,11 +1070,22 @@ p_audio_start_play(GapPlayerMainGlobalParams *gpp)
 /* -----------------------------
  * p_audio_startup_server
  * -----------------------------
+ * In case compiled with (older) wavplay client/server
+ * implementation, this method checks if the wavplay server
+ * is available.
+ *
+ * In case newer audiosupport  is availabel just enable the relevant GUI widgets
+ *
+ * In case audiosupport is NOT available 
+ *
  */
 static void
 p_audio_startup_server(GapPlayerMainGlobalParams *gpp)
 {
-#ifdef GAP_ENABLE_AUDIO_SUPPORT
+  gboolean l_audio_enable = FALSE;
+  
+    
+#ifdef GAP_ENABLE_AUDIO_SUPPORT_WAVPLAY
   const char *cp;
   gboolean wavplay_server_found;
 
@@ -1163,11 +1162,11 @@ p_audio_startup_server(GapPlayerMainGlobalParams *gpp)
   if(wavplay_server_found)
   {
     p_audio_filename_changed(gpp);
-    gpp->audio_enable = TRUE;
+    l_audio_enable = TRUE;
   }
   else
   {
-    gpp->audio_enable = FALSE;
+    l_audio_enable = FALSE;
     g_message(_("No audiosupport available\n"
                  "the audioserver executable file '%s' was not found.\n"
                  "If you have installed '%s'\n"
@@ -1179,7 +1178,15 @@ p_audio_startup_server(GapPlayerMainGlobalParams *gpp)
                  , "WAVPLAYPATH"
                  );
   }
+#else
+#ifdef GAP_ENABLE_AUDIO_SUPPORT
+    p_audio_filename_changed(gpp);
+    l_audio_enable = TRUE;
+#endif
+
 #endif
+
+  gpp->audio_enable = l_audio_enable;
   return;
 }  /* end p_audio_startup_server */
 
@@ -7202,7 +7209,7 @@ on_prefs_save_gimprc_button_clicked (GtkButton       *button,
   p_gimprc_save_boolean_option("video_player_enable_detail_tracking"
                              ,gpp->enableDetailTracking);
 
-  valueAsString = g_strdup_printf("%d", gpp->cache_ntiles);
+  valueAsString = g_strdup_printf("%ld", (long)gpp->cache_ntiles);
   gimp_gimprc_set("video_player_cache_ntiles", valueAsString);
   g_free(valueAsString);
   
diff --git a/gap/gap_sdl_audioplayer.c b/gap/gap_sdl_audioplayer.c
new file mode 100644
index 0000000..2b55004
--- /dev/null
+++ b/gap/gap_sdl_audioplayer.c
@@ -0,0 +1,933 @@
+/* gap_sdl_audioplayer.c
+ *  implements audio wavefile playback via SDL medialibrary.
+ *  (SDL is available for Linux, Windows and MacOS)
+ *
+ *  This player uses an interface that is compatible with
+ *  the wavplay client wrapper, but adds support for playback of
+ *  audio pcm data from a preloaded memory buffer.
+ *
+ * Note that the (older) wavplay server/client based audioplayback
+ * may be configured at compiletime as alternative on Linux only.
+ */
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <SDL.h>
+#include <SDL_audio.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <gap_sdl_audioplayer.h>
+
+#include <gap_audio_wav.h>
+
+
+#define NUM_SOUNDSLOTS 1   /* number of sounds that can be played (mixed) at same time */
+   /* Note that the current implementation is partly prepared for more than one sound at a time
+    * but limited to 1 Sound (due to wavplay compatible API that does not require this feature)
+    * Note that Playing from multiple slots also requires same audio parameters (channels, samplerate, format)
+    * for audio data in all slots.
+    */
+
+#define AUDIO_BUFFER_SIZE_IN_SAMPLES 4096
+
+/* The AUDIO_FILE_PACKET_SIZE shall be large enough to provide all requested samples (len)
+ * in the mixaudio_callback with only one file read (fread) operation for optimal performance.
+ * in tests on Linux systems a size of AUDIO_BUFFER_SIZE_IN_SAMPLES * 4 was sufficient
+ * but tests on Windows7 showed that the mixaudio_callback requested a len value of 44112 bytes.
+ * therfore the AUDIO_FILE_PACKET_SIZE was increased to AUDIO_BUFFER_SIZE_IN_SAMPLES * 32
+ * that should work on most systems.
+ * (smaller AUDIO_BUFFER_SIZE_IN_SAMPLES was also successfully tested on Windows7)
+ *
+ */
+#define AUDIO_FILE_PACKET_SIZE  (AUDIO_BUFFER_SIZE_IN_SAMPLES * 32)
+
+
+#define MAX_WAV_FILENAME_LENGTH 2048
+
+typedef struct {
+    Uint32            start_at_sample;  /* offset (where to start play) in number of audio frames */
+    int               mix_volume;       /* 0 upto SDL_MIX_MAXVOLUME (Note this does not change hardware volume.) */
+
+    /* preloaded memory slot (relevant in case data != NULL) */
+    Uint8 *data;   /* the audio sample data */
+    Uint32 dpos;   /* the current data position in bytes (points to rest of data that has not yet been played) */
+    Uint32 dlen;   /* the length of audio sample data in bytes */
+
+    /* file based audio slot */
+    FILE             *fpWav;                       /* filehandle to read from audio wavefile */
+    long              offset_to_first_sample;      /* fseek offset to the 1st sample data byte in the audio wavefile */
+    Uint8             audio_buf[AUDIO_FILE_PACKET_SIZE];  /* buffer for fetching audio sample data from file */
+    char              wav_filename[MAX_WAV_FILENAME_LENGTH];   /* the name of the audio file to be played  */
+} AudioSlot;
+
+
+typedef struct
+{
+  /* audio params */
+  unsigned int      samplerate;
+  unsigned int      channels;
+  unsigned int      bits_per_sample;
+  unsigned int      frame_size;       /* frame_size = (bits_per_sample / 8) * channels */
+  unsigned int      format;           /* AUDIO_S16, AUDIO_U8, ... */
+
+  /* private attribuites (managed by the playback_callback thread only) */
+  SDL_AudioSpec     sdlAudioSpec;
+  AudioSlot         sounds[NUM_SOUNDSLOTS];
+
+} AudioPlaybackThreadUserData;
+
+
+static AudioPlaybackThreadUserData *audioPlaybackThreadUserDataPtr = NULL;
+
+extern int gap_debug;
+
+/* ------------------------------------------------
+ * call_errfunc
+ * ------------------------------------------------
+ * Error reporting function for this source module:
+ */
+static void
+call_errfunc(GapSdlErrFunc v_erf, const char *format,...) {
+  va_list ap;
+
+  if ( v_erf == NULL )
+  {
+    return;                             /* Only report error if we have function */
+  }
+  va_start(ap,format);
+  v_erf(format,ap);                     /* Use caller's supplied function */
+  va_end(ap);
+}
+
+/* -------------------------------------
+ * mixaudio_callback
+ * -------------------------------------
+ * this callback function will be called when the audio device is ready for more data.
+ * It is passed a pointer to user specific data, the audio buffer, and the length in bytes of the audio buffer.
+ * This function usually runs in a separate thread, and so access to data structures
+ * must be protected by calling SDL_LockAudio and SDL_UnlockAudio.
+ *
+ * This callback fetches audio data from preloaded memory (at address usrPtr->sounds[i].data)
+ * or tries to fetch from file
+ *    in case address usrPtr->sounds[i].data is NULL and
+ *    usrPtr->sounds[i].fpWav  refers to an audiofile opened for read access.
+ *
+ * it is assumed that the audiofile contains uncopressed PCM data
+ * matching the current audio playback settings (channels, samplerate, bits_per_sample,...)
+ * .. e.g no converting of different channels, samplerates is done in this function.
+ */
+void mixaudio_callback(void *userData, Uint8 *stream, int len)
+{
+  int ii;
+  Uint32 amount;
+  AudioPlaybackThreadUserData *usrPtr;
+
+
+  usrPtr = (AudioPlaybackThreadUserData *) userData;
+  if (usrPtr == NULL)
+  {
+    return;
+  }
+
+  SDL_LockAudio();
+
+  for (ii=0; ii < NUM_SOUNDSLOTS; ii++)
+  {
+    if (usrPtr->sounds[ii].data == NULL)
+    {
+      int lenRest;
+      int lenToDeliver;
+      Uint8 *streamPos;
+
+      lenToDeliver = len;
+      streamPos = stream;
+
+      while(lenToDeliver > 0)
+      {
+        lenRest = MIN(lenToDeliver, AUDIO_FILE_PACKET_SIZE);
+        amount = AUDIO_FILE_PACKET_SIZE;
+        if ( amount > lenRest )
+        {
+          amount = lenRest;
+        }
+        /* try fetch data packet direct from file */
+        if ((usrPtr->sounds[ii].fpWav == NULL) || (amount <= 0))
+        {
+          /* file not available (already closed when plyaed until end */
+          amount = 0;
+        }
+        else
+        {
+          int  datasize;
+          datasize = fread(&usrPtr->sounds[ii].audio_buf[0]
+                  , 1
+                  , amount
+                  , usrPtr->sounds[ii].fpWav
+                  );
+          if(gap_debug)
+          {
+            printf("mixaudio_callback fread amount:%d datasize:%d len:%d lenToDeliver:%d lenRest:%d mix_volume:%d\n"
+                , amount
+                , datasize
+                , len
+                , lenToDeliver
+                , lenRest
+                , (int)usrPtr->sounds[ii].mix_volume
+                );
+          }
+          if (datasize != amount)
+          {
+            if (datasize > 0)
+            {
+              amount = datasize;
+            }
+            else
+            {
+              amount = 0;
+            }
+          }
+
+        }
+        SDL_MixAudio(streamPos
+                , &usrPtr->sounds[ii].audio_buf[0]
+                , amount
+                , usrPtr->sounds[ii].mix_volume
+                );
+        if(amount < lenRest)
+        {
+          break;
+        }
+        lenToDeliver -= amount;
+        streamPos += amount;
+
+      }
+
+
+    }
+    else
+    {
+      /* fetch data from preloaded memory data buffer */
+      amount = (usrPtr->sounds[ii].dlen - usrPtr->sounds[ii].dpos);
+      if ( amount > len )
+      {
+        amount = len;
+      }
+      if(gap_debug)
+      {
+          printf("mixaudio_callback mix amount:%d len:%d mix_volume:%d\n"
+                , amount
+                , len
+                , (int)usrPtr->sounds[ii].mix_volume
+                );
+      }
+      SDL_MixAudio(stream
+                , &usrPtr->sounds[ii].data[usrPtr->sounds[ii].dpos]
+                , amount
+                , usrPtr->sounds[ii].mix_volume
+                );
+      usrPtr->sounds[ii].dpos += amount;
+    }
+  }
+
+  SDL_UnlockAudio();
+
+}  /* end mixaudio_callback */
+
+
+
+/* ------------------------------------------------
+ * newAudioPlaybackThreadUserData
+ * ------------------------------------------------
+ * allocate a new AudioPlaybackThreadUserData structure
+ * and initialize with default values.
+ */
+static AudioPlaybackThreadUserData *
+newAudioPlaybackThreadUserData()
+{
+  int ii;
+  AudioPlaybackThreadUserData  *usrPtr;
+
+  /* init user data for the audio_playback_thread */
+  usrPtr = g_new0 (AudioPlaybackThreadUserData, 1);
+
+  /* prepared parameters (relevant for next playback start) */
+  usrPtr->samplerate = 44100;
+  usrPtr->channels = 2;
+  usrPtr->bits_per_sample = 16;
+  usrPtr->frame_size = (usrPtr->bits_per_sample / 8) * usrPtr->channels;
+  usrPtr->format = AUDIO_S16;
+
+  /* actual parameters (relevant for playback) */
+  usrPtr->sdlAudioSpec.freq = 44100;
+  usrPtr->sdlAudioSpec.format = AUDIO_S16;
+  usrPtr->sdlAudioSpec.channels = 2;
+  usrPtr->sdlAudioSpec.samples = AUDIO_BUFFER_SIZE_IN_SAMPLES;   /* 512 upto 8192 are recommanded values */
+  usrPtr->sdlAudioSpec.callback = mixaudio_callback;
+  usrPtr->sdlAudioSpec.userdata = usrPtr;
+
+
+  /* init sound slots (relevant for filling audio buffer
+   * at playback int mixaudio_callback thread)
+   */
+  for (ii=0; ii < NUM_SOUNDSLOTS; ii++)
+  {
+    usrPtr->sounds[ii].start_at_sample = 0;
+    usrPtr->sounds[ii].mix_volume = SDL_MIX_MAXVOLUME;
+    usrPtr->sounds[ii].data = NULL;
+    usrPtr->sounds[ii].dpos = 0;
+    usrPtr->sounds[ii].dlen = 0;
+
+    usrPtr->sounds[ii].fpWav = NULL;
+    usrPtr->sounds[ii].offset_to_first_sample = 0;
+    usrPtr->sounds[ii].wav_filename[0] = '\0';
+  }
+
+  return (usrPtr);
+
+}  /* end newAudioPlaybackThreadUserData */
+
+
+/* ------------------------------------------------
+ * getUsrPtr
+ * ------------------------------------------------
+ */
+static AudioPlaybackThreadUserData *
+getUsrPtr()
+{
+  AudioPlaybackThreadUserData  *usrPtr;
+  if (audioPlaybackThreadUserDataPtr == NULL)
+  {
+    audioPlaybackThreadUserDataPtr = newAudioPlaybackThreadUserData();
+  }
+
+  usrPtr = audioPlaybackThreadUserDataPtr;
+  return (usrPtr);
+
+}  /* end getUsrPtr */
+
+/* ------------------------------------------------
+ * close_files
+ * ------------------------------------------------
+ */
+static void
+close_files()
+{
+  AudioPlaybackThreadUserData  *usrPtr;
+
+  usrPtr = getUsrPtr();
+  if (usrPtr != NULL)
+  {
+    int ii;
+
+    SDL_LockAudio();
+    for (ii=0; ii < NUM_SOUNDSLOTS; ii++)
+    {
+      if (usrPtr->sounds[ii].fpWav != NULL)
+      {
+        fclose(usrPtr->sounds[ii].fpWav);
+        usrPtr->sounds[ii].fpWav = NULL;
+      }
+    }
+    SDL_UnlockAudio();
+  }
+
+}  /* end close_files */
+
+
+/* ------------------------------------------------
+ * stop_audio
+ * ------------------------------------------------
+ */
+static void
+stop_audio()
+{
+  AudioPlaybackThreadUserData  *usrPtr;
+
+  usrPtr = getUsrPtr();
+  if (usrPtr != NULL)
+  {
+    SDL_LockAudio();
+
+    if(SDL_GetAudioStatus() != SDL_AUDIO_STOPPED)
+    {
+      SDL_CloseAudio();
+    }
+    SDL_UnlockAudio();
+  }
+
+}  /* end stop_audio */
+
+
+/* ------------------------------------------------
+ * start_audio
+ * ------------------------------------------------
+ * init SDL audio with new (pending) setings and (re)start audio playback
+ * from prepared position "start_at_sample"
+ * (e.g. from begin in case gap_sdl_start_sample was not called before)
+ *
+ * in case audio is already playing stop it, and restart with the new settings.
+ */
+static int
+start_audio()
+{
+  AudioPlaybackThreadUserData  *usrPtr;
+  int ii;
+
+  usrPtr = getUsrPtr();
+  if (usrPtr == NULL)
+  {
+    return (1);
+  }
+
+  SDL_LockAudio();
+  if(SDL_GetAudioStatus() != SDL_AUDIO_STOPPED)
+  {
+    SDL_CloseAudio();
+  }
+
+  for (ii=0; ii < NUM_SOUNDSLOTS; ii++)
+  {
+    if (usrPtr->sounds[ii].data == NULL)
+    {
+      if (usrPtr->sounds[ii].fpWav == NULL)
+      {
+        usrPtr->sounds[ii].fpWav = gap_audio_wav_open_seek_data(usrPtr->sounds[ii].wav_filename);
+      }
+
+      if (usrPtr->sounds[ii].fpWav != NULL)
+      {
+        long seekPosition;
+
+        seekPosition = usrPtr->sounds[ii].offset_to_first_sample
+                     + (usrPtr->sounds[ii].start_at_sample * usrPtr->frame_size);
+
+        fseek(usrPtr->sounds[ii].fpWav, seekPosition, SEEK_SET);
+      }
+    }
+    else
+    {
+      usrPtr->sounds[ii].dpos = usrPtr->sounds[ii].start_at_sample * usrPtr->frame_size;
+      if (usrPtr->sounds[ii].dpos >= usrPtr->sounds[ii].dlen)
+      {
+        /* reset to begin on illegal start position */
+        usrPtr->sounds[ii].dpos = 0;
+      }
+    }
+  }
+
+
+  /* load sdlAudioSpec (relevant for playback) from prepared values */
+  usrPtr->sdlAudioSpec.freq = usrPtr->samplerate;
+  usrPtr->sdlAudioSpec.format = usrPtr->format;
+  usrPtr->sdlAudioSpec.channels = usrPtr->channels;
+  usrPtr->sdlAudioSpec.samples = AUDIO_BUFFER_SIZE_IN_SAMPLES;        /* audio buffer size (512 upto 8192 recommanded) */
+
+
+  SDL_UnlockAudio();
+  if ( SDL_OpenAudio(&usrPtr->sdlAudioSpec, NULL) < 0 )
+  {
+    /* Unable to open audio use SDL_GetError() to query reason */
+    return(2);
+  }
+
+  SDL_PauseAudio(0);  /* pause value 0 triggers playback start */
+
+  return (0);  /* OK */
+
+}  /* end start_audio */
+
+
+
+/* -------------------------------------
+ * gap_sdl_start
+ * -------------------------------------
+ * prepare the audio_playback.
+ * (not mandatory in this SDL based implementation)
+ */
+int
+gap_sdl_start(GapSdlErrFunc erf)
+{
+  AudioPlaybackThreadUserData  *usrPtr;
+
+  usrPtr = getUsrPtr();
+  if (usrPtr != NULL)
+  {
+    return (0);  /* OK */
+  }
+
+  call_errfunc(erf, "failed to prepare audio_playback.");
+  return (1);
+
+}  /* end gap_sdl_start */
+
+
+/* -------------------------------------
+ * gap_sdl_memory_buffer
+ * -------------------------------------
+ */
+int
+gap_sdl_memory_buffer(char *buffer, long buffer_len, GapSdlErrFunc erf)
+{
+  int rc = 1;
+  int ii = 0;
+  AudioPlaybackThreadUserData  *usrPtr;
+
+  usrPtr = getUsrPtr();
+  if (usrPtr != NULL)
+  {
+    stop_audio();
+    usrPtr->sounds[ii].data = buffer;   /* point to memory provided by the caller */
+    usrPtr->sounds[ii].dpos = 0;
+    usrPtr->sounds[ii].dlen = buffer_len;
+
+    if (usrPtr->sounds[ii].fpWav != NULL)
+    {
+      fclose(usrPtr->sounds[ii].fpWav);
+      usrPtr->sounds[ii].fpWav = NULL;
+    }
+    rc = 0;  /* OK */
+  }
+
+  if ( (rc != 0) && (erf != NULL) )
+  {
+    call_errfunc(erf, "memory_buffer: %ld len: %ld not accepted", (long)&buffer, buffer_len);
+  }
+
+  return (rc);
+
+}  /* end gap_sdl_memory_buffer */
+
+
+
+/* -------------------------------------
+ * gap_sdl_path
+ * -------------------------------------
+ *
+ * Send a pathname to the audio_player.
+ * (use flags =1 to keep current playback parameters)
+ * typical call with flags == 0 does init the audio playback parameters
+ * from the header information of the specified RIFF WAVE file (rfered by pathname)
+ */
+int
+gap_sdl_path(const char *pathname,int flags,GapSdlErrFunc erf)
+{
+  int rc = 1;
+  AudioPlaybackThreadUserData  *usrPtr;
+
+  usrPtr = getUsrPtr();
+  if (usrPtr != NULL)
+  {
+    int rcCheck;
+    long sample_rate;
+    long channels;
+    long bytes_per_sample;
+    long bits;
+    long samples;
+
+    rcCheck = gap_audio_wav_file_check(pathname, &sample_rate, &channels
+                           , &bytes_per_sample, &bits, &samples);
+    if (rcCheck == 0)
+    {
+      int ii;
+
+      rc = 0;  /* OK */
+      ii = 0;
+      stop_audio();
+      usrPtr->sounds[ii].data = NULL;   /* no preloded memory available */
+      usrPtr->sounds[ii].dpos = 0;
+      usrPtr->sounds[ii].dlen = 0;
+
+
+      if (flags != 1)
+      {
+        /* set audio params from wavefile header */
+        usrPtr->format = AUDIO_S16;
+
+        usrPtr->samplerate = sample_rate;
+        usrPtr->channels = channels;
+        usrPtr->bits_per_sample = bits;
+        usrPtr->frame_size = (usrPtr->bits_per_sample / 8) * usrPtr->channels;
+        switch (bits)
+        {
+          case 8:
+            usrPtr->format = AUDIO_U8;
+            break;
+          case 16:
+            usrPtr->format = AUDIO_S16;  /* same as AUDIO_S16LSB */
+            break;
+          default:
+            rc = 2;  /* unsupported bits_per_channel value */
+            break;
+        }
+      }
+      if (rc == 0)
+      {
+        if (usrPtr->sounds[ii].fpWav != NULL)
+        {
+          if (strcmp(usrPtr->sounds[ii].wav_filename, pathname) != 0)
+          {
+            /* file differs from currently opened wavfile, force close/reopen */
+            fclose(usrPtr->sounds[ii].fpWav);
+            usrPtr->sounds[ii].fpWav = NULL;
+          }
+          else
+          {
+            long seekPosition;
+
+            /* current wavfile was specified again, just rewind existing filehandle */
+            seekPosition = usrPtr->sounds[ii].offset_to_first_sample;
+            fseek(usrPtr->sounds[ii].fpWav, seekPosition, SEEK_SET);
+          }
+        }
+
+        if (usrPtr->sounds[ii].fpWav == NULL)
+        {
+          g_snprintf(usrPtr->sounds[ii].wav_filename, MAX_WAV_FILENAME_LENGTH -1, pathname);
+          usrPtr->sounds[ii].wav_filename[MAX_WAV_FILENAME_LENGTH -1] = '\0';
+          usrPtr->sounds[ii].offset_to_first_sample = 0;
+          usrPtr->sounds[ii].fpWav = gap_audio_wav_open_seek_data(usrPtr->sounds[ii].wav_filename);
+        }
+
+        if(usrPtr->sounds[ii].fpWav == NULL)
+        {
+          rc = 3;  /* failed to open audio data file */
+        }
+        else
+        {
+          /* store current file offset (position of the 1st audio sample data byte) */
+          usrPtr->sounds[ii].offset_to_first_sample = ftell(usrPtr->sounds[ii].fpWav);
+        }
+      }
+
+    }
+  }
+
+  if ( (rc != 0) && (erf != NULL) )
+  {
+     if (pathname != NULL)
+     {
+       // TODO provide to_string for errorcodes rc
+       call_errfunc(erf, "path: Not a valid RIFF WAVE file %s rc:%d (%s)", pathname, rc, " ");
+     }
+     else
+     {
+       call_errfunc(erf, "path: is NULL (name of RIFF WAVE file was expected).");
+     }
+  }
+
+  return (rc);
+
+}  /* end gap_sdl_path */
+
+
+/* -------------------------------------
+ * gap_sdl_volume
+ * -------------------------------------
+ * Tell audio_player to use mix volume (0.0 upto 1.0)
+ * (Note: this does not set the hardware audio volume,
+ *  values smaller than 1 may reduce the sound quality due to data loss while mix down)
+ */
+int
+gap_sdl_volume(double volume, int flags, GapSdlErrFunc erf)
+{
+  int rc = 1;
+  AudioPlaybackThreadUserData  *usrPtr;
+
+  usrPtr = getUsrPtr();
+  if (usrPtr != NULL)
+  {
+    if ((volume >= 0.0) && (volume <= 1.0))
+    {
+      int ii = 0;
+      gdouble mixVolumeDouble;
+
+      SDL_LockAudio();
+      mixVolumeDouble = SDL_MIX_MAXVOLUME;
+      mixVolumeDouble = mixVolumeDouble * volume;
+      usrPtr->sounds[ii].mix_volume = (int)mixVolumeDouble;
+      SDL_UnlockAudio();
+
+      rc = 0;  /* OK */
+    }
+  }
+
+  if ( (rc != 0) && (erf != NULL) )
+  {
+    call_errfunc(erf, "volume: value %f not accepted (valid range is 0.0 to 1.0)", (float)volume);
+  }
+
+  return (rc);
+
+}  /* end gap_sdl_volume */
+
+
+/* -------------------------------------
+ * gap_sdl_channels
+ * -------------------------------------
+ *  Tell audio_player the number of channels
+ */
+int
+gap_sdl_channels(int flags,GapSdlErrFunc erf, int channels)
+{
+  int rc = 1;
+  AudioPlaybackThreadUserData  *usrPtr;
+
+  usrPtr = getUsrPtr();
+  if (usrPtr != NULL)
+  {
+    usrPtr->channels = channels;
+    usrPtr->frame_size = (usrPtr->bits_per_sample / 8) * usrPtr->channels;
+    rc = 0;  /* OK */
+  }
+
+  if ( (rc != 0) && (erf != NULL) )
+  {
+    call_errfunc(erf, "channels: %d not accepted", channels);
+  }
+
+  return (rc);
+
+}  /* end gap_sdl_channels */
+
+
+/* -------------------------------------
+ * gap_sdl_bits
+ * -------------------------------------
+ * Tell audio_player about new data bits per sample and sample format setting:
+ * flags: 0  signed sample   little endian (AUDIO_S8, AUDIO_S16LSB)
+ * flags: 1  unsigned sample little endian (AUDIO_U8, AUDIO_U16LSB)
+ * flags: 2  signed sample   big endian    (AUDIO_S16MSB)
+ * flags: 3  unsigned sample big endian    (AUDIO_U16MSB)
+ */
+int
+gap_sdl_bits(int flags,GapSdlErrFunc erf,int bits)
+{
+  int rc = 1;
+  AudioPlaybackThreadUserData  *usrPtr;
+
+  usrPtr = getUsrPtr();
+  if (usrPtr != NULL)
+  {
+    rc = 0;  /* OK */
+    switch (bits)
+    {
+      case 8:
+        usrPtr->bits_per_sample = bits;
+        if ((flags & 1) != 0) { usrPtr->format = AUDIO_U8; }
+        else                  { usrPtr->format = AUDIO_S8; }
+        break;
+      case 16:
+        usrPtr->bits_per_sample = bits;
+        if      ((flags & 3) == 1) { usrPtr->format = AUDIO_U16LSB; }
+        else if ((flags & 3) == 2) { usrPtr->format = AUDIO_S16MSB; }
+        else if ((flags & 3) == 3) { usrPtr->format = AUDIO_U16MSB; }
+        else                       { usrPtr->format = AUDIO_S16; }  /* same as AUDIO_S16LSB */
+        break;
+      default:
+        rc = 2;  /* unsupported bits_per_channel value */
+        break;
+    }
+    usrPtr->frame_size = (usrPtr->bits_per_sample / 8) * usrPtr->channels;
+  }
+
+  if ( (rc != 0) && (erf != NULL) )
+  {
+    call_errfunc(erf, "bits: %d not accepted", bits);
+  }
+
+  return (rc);
+
+}  /* end gap_sdl_bits */
+
+
+
+
+/* -------------------------------------
+ * gap_sdl_sampling_rate
+ * -------------------------------------
+ * Tell audio_player to use new sampling rate:
+ */
+int
+gap_sdl_sampling_rate(int flags,GapSdlErrFunc erf,Uint32 sampling_rate)
+{
+  int rc = 1;
+  AudioPlaybackThreadUserData  *usrPtr;
+
+  usrPtr = getUsrPtr();
+  if (usrPtr != NULL)
+  {
+    usrPtr->samplerate = sampling_rate;
+    rc = 0;  /* OK */
+  }
+
+  if ( (rc != 0) && (erf != NULL) )
+  {
+    call_errfunc(erf, "sampling_rate: %d not accepted", sampling_rate);
+  }
+
+  return (rc);
+
+}  /* end gap_sdl_sampling_rate */
+
+
+
+
+/* -------------------------------------
+ * gap_sdl_start_sample
+ * -------------------------------------
+ * Tell audio_player to start at a new sample number:
+ */
+int
+gap_sdl_start_sample(int flags, GapSdlErrFunc erf, Uint32 sample)
+{
+  int rc = 1;
+  int ii = 0;
+  AudioPlaybackThreadUserData  *usrPtr;
+
+  usrPtr = getUsrPtr();
+  if (usrPtr != NULL)
+  {
+    usrPtr->sounds[ii].start_at_sample = sample;
+    rc = 0;  /* OK */
+  }
+
+  if ( (rc != 0) && (erf != NULL) )
+  {
+    call_errfunc(erf, "start_sample: %d not accepted", (int)sample);
+  }
+
+  return rc;
+
+}  /* end gap_sdl_start_sample */
+
+
+
+/* -------------------------------------
+ * msg_name
+ * -------------------------------------
+ * convert int cmd to readable string representation.
+ */
+static const char *
+msg_name(int cmd)
+{
+  switch(cmd)
+  {
+    case GAP_SDL_CMD_Bye:
+      return ("GAP_SDL_CMD_Bye");
+      break;
+    case GAP_SDL_CMD_Play:
+      return ("GAP_SDL_CMD_Play");
+      break;
+    case GAP_SDL_CMD_Pause:
+      return ("GAP_SDL_CMD_Pause");
+      break;
+    case GAP_SDL_CMD_Stop:
+      return ("GAP_SDL_CMD_Stop");
+      break;
+    case GAP_SDL_CMD_Restore:
+      return ("GAP_SDL_CMD_Restore");
+      break;
+    case GAP_SDL_CMD_SemReset:
+      return ("GAP_SDL_CMD_SemReset");
+      break;
+  }
+  return ("unknown");
+
+}  /* end msg_name */
+
+
+/* -------------------------------------
+ * gap_sdl_cmd
+ * -------------------------------------
+ * perform simple audio_player command .
+ * Note: some of the commands do not make sense
+ *       in this SDL based implementation
+ *       and are just dummies for compatibility with the
+ *       API (that was designed base on the older wavplay client functions)
+ */
+int
+gap_sdl_cmd(int cmd,int flags,GapSdlErrFunc erf) {
+  static char *sdl_no_error_available = "";
+  char *sdl_error;
+  int rc = 1;
+  AudioPlaybackThreadUserData  *usrPtr;
+
+
+  sdl_error = sdl_no_error_available;
+  usrPtr = getUsrPtr();
+  if (usrPtr != NULL)
+  {
+    if(gap_debug)
+    {
+      printf("gap_sdl_cmd cmd:%d (%s) flags:%d SdlAudioStatus:%d\n"
+            , cmd
+           , msg_name(cmd)
+           , flags
+           , (int)SDL_GetAudioStatus()
+           );
+    }
+    switch(cmd)
+    {
+      case GAP_SDL_CMD_Bye:
+        stop_audio();
+        close_files();
+        rc = 0;  /* OK */
+        break;
+      case GAP_SDL_CMD_Play:
+        rc = start_audio();
+        sdl_error = SDL_GetError();  /* SDL_GetError uses sttically allocated message that must NOT be freed */
+        break;
+      case GAP_SDL_CMD_Pause:
+        stop_audio();
+        rc = 0;  /* OK */
+        break;
+      case GAP_SDL_CMD_Stop:
+        stop_audio();
+        close_files();
+        rc = 0;  /* OK */
+        break;
+      case GAP_SDL_CMD_Restore:
+        stop_audio();
+        rc = 0;  /* OK */
+        break;
+      case GAP_SDL_CMD_SemReset:
+        rc = 0;  /* OK */
+        break;
+    }
+
+  }
+
+
+  if ((rc != 0) && (erf != NULL ))
+  {
+    call_errfunc(erf, "%s: Sending cmd%d to audio_player failed (rc:%d) err:%s",
+                        msg_name(cmd),
+                        cmd,
+                        sdl_error,
+                        rc);
+  }
+  if(gap_debug)
+  {
+    printf("gap_sdl_cmd cmd:%d (%s) flags:%d retcode:%d\n", cmd, msg_name(cmd), flags, rc);
+  }
+  return rc;  /* Zero indicates success */
+
+}  /* end gap_sdl_cmd */
diff --git a/gap/gap_sdl_audioplayer.h b/gap/gap_sdl_audioplayer.h
new file mode 100644
index 0000000..f3044e7
--- /dev/null
+++ b/gap/gap_sdl_audioplayer.h
@@ -0,0 +1,129 @@
+/* gap_sdl_audioplayer.h
+ *  provides audio wavefile playback via SDL medialibrary.
+ *  (SDL is available for Linux, Windows and MacOS)
+ *
+ *  This player uses an interface that is compatible with
+ *  the wavplay client wrapper, but adds support for playback of
+ *  audio pcm data from a preloaded memory buffer.
+ *
+ * Note that the (older) wavplay server/client based audioplayback
+ * may be configured at compiletime as alternative on Linux only.
+ *
+ */
+/* The GIMP -- an image manipulation program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _GAP_SDL_AUDIOPLAYER_H
+#define _GAP_SDL_AUDIOPLAYER_H
+
+#include <stdarg.h>
+#include <sys/types.h>
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <SDL.h>
+#include <SDL_audio.h>
+
+
+
+
+typedef void (*GapSdlErrFunc)(const char *format,va_list ap);
+
+#define GAP_SDL_CMD_Bye      0
+#define GAP_SDL_CMD_Play     1
+#define GAP_SDL_CMD_Pause    2
+#define GAP_SDL_CMD_Stop     3
+#define GAP_SDL_CMD_Restore  4
+#define GAP_SDL_CMD_SemReset 5
+
+
+/*
+ * start the audio_playback thread.
+ */
+int  gap_sdl_start(GapSdlErrFunc erf);
+
+/*
+ * Tell audio_player a buffer with PCM audiodata
+ * Fetch of audio data switches to the specified memory buffer
+ * where following default playback settings are automatically established:
+ *  samplerate: 44100 Hz.
+ *  bits: 16 (SND_PCM_FORMAT_S16_LE)
+ *  channels: 2
+ *
+ * IMPORTANT: the buffer MUST be aligned at short boundaries
+ * (e.g do not allocate the memory as char that would lead to a crash)
+ */
+int  apcl_memory_buffer(char *buffer, long buffer_len, GapSdlErrFunc erf);
+
+/*
+ * Send simple command to audio_player:
+ */
+int  gap_sdl_cmd(int cmd, int flags, GapSdlErrFunc erf);
+
+/*
+ * Send a pathname to the audio_player:
+ * The patrhname must refere to a RIFF WAVE fmt file.
+ *
+ * Note: to trigger audio playback the
+ * audio_playback thread must be started { call gap_sdl_start(NULL) }
+ * and playback must be turned on (call gap_sdl_cmd(GAP_SDL_CMD_Play,0,NULL)
+ *
+ * flags: 0 set audio hardware parameters (samplerate, channels,...) from the wavefile specified by path.
+ * flags: 1 keep current audio hardware parameters.
+ *          (you may use this in case your program has already explicite set
+ *           the wanted samplerate, channels, ... )
+ *
+ * returns 0 OK, 1 if pathname is not readable as valid RIFF WAVE file.
+ */
+int  gap_sdl_path(const char *pathname, int flags, GapSdlErrFunc erf);
+
+/*
+ * Tell audio_player about new data bits per sample and sample format setting:
+ * flags: 0  signed sample   little endian (AUDIO_S8, AUDIO_S16LSB)
+ * flags: 1  unsigned sample little endian (AUDIO_U8, AUDIO_U16LSB)
+ * flags: 2  signed sample   big endian    (AUDIO_S16MSB)
+ * flags: 3  unsigned sample big endian    (AUDIO_U16MSB)
+ */
+int  gap_sdl_bits(int flags,GapSdlErrFunc erf,int bits);
+
+/*
+ * Tell audio_player to start at a new sample number:
+ */
+int  gap_sdl_start_sample(int flags, GapSdlErrFunc erf, Uint32 sample);
+
+/*
+ * Tell audio_player to use new sampling rate:
+ */
+int  gap_sdl_sampling_rate(int flags, GapSdlErrFunc erf, Uint32 sampling_rate);
+
+/*
+ * Tell audio_player to use new number of channels (1 for Mono, 2 for Stereo)
+ */
+int  gap_sdl_channels(int flags,GapSdlErrFunc erf, int channels);
+
+/*
+ * Tell audio_player to use mix volume (0.0 upto 1.0)
+ *
+ *  flags: 0  use mix volume. Note that this does not set the hardware audio volume,
+ *            but downscales all processed samples.
+ *            (Where values smaller than 1 may reduce the sound quality
+ *             due to data loss while mix down)
+ *  flags: 1  use master volume of the audio device (TODO: NOT YET supported)
+ */
+int  gap_sdl_volume(double volume, int flags, GapSdlErrFunc erf);
+
+#endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]