new file mode 100644
--- /dev/null
+++ b/src/audioplayer.c
@@ -0,0 +1,232 @@
+/**
+ * $Id: audioplayer.c 53 2008-01-10 00:19:41Z mbroeker $
+ * $URL: http://localhost/svn/c/VirtualReader/trunk/src/audioplayer.c $
+ */
+
+#include <audioplayer.h>
+
+typedef struct {
+ SDL_AudioSpec spec; // internal structure
+ Uint8 *sound_buffer; // malloced pointer from sdl
+ Uint32 sound_pos; // position
+ Uint32 sound_len; // length in bytes
+ Uint32 length; // Length in Milliseconds
+
+ int opened; // bool opened
+ int loaded; // bool loaded
+ int verbose; // verbose messages
+ int timeout; // timeout
+ int timer; // bool timer
+} AudioDevice;
+
+AudioDevice AD;
+
+int audio_init ()
+{
+ /*
+ * initialize SDL for audio output
+ */
+ if (SDL_Init (SDL_INIT_AUDIO) < 0) {
+ fprintf (stderr, "audio_init: Cannot initialize SDL-Subsystem\n");
+ return -1;
+ }
+
+ AD.sound_buffer = 0;
+ AD.sound_pos = 0;
+ AD.sound_len = 0;
+
+ AD.opened = 0;
+ AD.loaded = 0;
+ AD.verbose = 0;
+
+ AD.timeout = 0;
+ AD.timer = 0;
+
+ return 0;
+}
+
+void audio_shutdown ()
+{
+ /*
+ * quit sdl
+ */
+ SDL_AudioQuit ();
+ SDL_Quit ();
+}
+
+static void Callback (void *userdata, Uint8 * stream, int len)
+{
+ Uint8 *waveptr = NULL;
+
+ /*
+ * loaded = 0 Segmentation fault
+ * len = 0 nothing to play
+ */
+ if (!(AD.loaded && len))
+ return;
+
+ waveptr = AD.sound_buffer + AD.sound_pos;
+ SDL_MixAudio (stream, waveptr, len, SDL_MIX_MAXVOLUME);
+ AD.sound_pos += len; /* bereits gespielt */
+
+ if (audioplayer_gettime () > (AD.length - AD.timeout)) {
+ AD.sound_pos = AD.length;
+ AD.sound_len = 0;
+ AD.timer = 0;
+ }
+}
+
+Uint32 audioplayer_getsoundlen ()
+{
+ return AD.sound_len;
+}
+
+void audioplayer_media_info (char *fname)
+{
+ AD.length = audioplayer_getwavelength (fname);
+
+ printf ("Playing %s: %d Hz, %d Bit Audio, %d Channel(s), %3.2d ms\n",
+ fname, AD.spec.freq, audioplayer_getbitrate (), AD.spec.channels, AD.length);
+}
+
+int audioplayer_getbitrate ()
+{
+ int bitrate = 0;
+
+ switch (AD.spec.format) {
+ case AUDIO_U8:
+ case AUDIO_S8:
+ bitrate = 8;
+ break;
+ case AUDIO_S16LSB:
+ case AUDIO_S16MSB:
+ case AUDIO_U16LSB:
+ case AUDIO_U16MSB:
+ bitrate = 16;
+ break;
+ }
+
+ return bitrate;
+}
+
+Uint32 audioplayer_getwavelength (char *fname)
+{
+ struct stat info;
+ Uint32 value = 0;
+
+ if (fname == NULL)
+ return AD.length;
+
+ if (stat (fname, &info) == 0)
+ /*
+ * the value is really big, so be carefull
+ * changes in the order result in different values
+ * the storage type isn`t well choosen...
+ */
+ value = ((info.st_size) / (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0)) * 1000.0);
+
+ return (value);
+}
+
+Uint32 audioplayer_getposition ()
+{
+ return AD.sound_pos;
+}
+
+Uint32 audioplayer_gettime ()
+{
+ Uint32 ret;
+
+ ret = AD.sound_pos / (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0)) * 1000.0;
+
+ return ret;
+}
+
+void audioplayer_settime (long tm)
+{
+ AD.sound_pos = tm / 1000.0 * (AD.spec.freq * AD.spec.channels * (audioplayer_getbitrate () / 8.0));
+
+ /*
+ * Eine Adresse ...
+ */
+ while ((AD.sound_pos % 2) != 0)
+ AD.sound_pos++;
+
+ if (AD.verbose)
+ printf ("\e[31m[ATTENTION]\e[37m [#%d/#%d] = %d ms\n", AD.sound_pos, AD.sound_len, audioplayer_gettime ());
+}
+
+void audioplayer_stop ()
+{
+ /*
+ * stops the callback function
+ */
+ SDL_PauseAudio (1);
+ AD.spec.callback = NULL;
+
+ if (AD.loaded == 1)
+ SDL_FreeWAV (AD.sound_buffer);
+
+ AD.loaded = 0;
+ AD.timer = 0;
+}
+
+void audioplayer_delay (Uint32 milliseconds)
+{
+ struct timespec tm;
+
+ tm.tv_sec = 0;
+ tm.tv_nsec = milliseconds * 1000;
+
+ while (AD.timer)
+ nanosleep (&tm, NULL);
+}
+
+void audioplayer_setverbose (int verbose)
+{
+ AD.verbose = verbose;
+}
+
+int audioplayer (char *fname, Uint32 timeout)
+{
+ if (SDL_LoadWAV (fname, &AD.spec, &AD.sound_buffer, &AD.sound_len) == NULL) {
+ printf ("SDL: %s\n", SDL_GetError ());
+ return -1;
+ }
+
+ AD.loaded = 1;
+
+ if (!AD.opened) {
+ AD.spec.callback = Callback;
+ if (SDL_OpenAudio (&AD.spec, NULL) < 0) {
+ fprintf (stderr, "Cannot open audio device: %s\n", SDL_GetError ());
+ return -1;
+ }
+ AD.opened = 1;
+ }
+
+ /*
+ * calls implicitly getwavelength
+ */
+ audioplayer_media_info (fname);
+
+ AD.sound_pos = 0;
+
+ /*
+ * starts playback via Callback function
+ */
+ SDL_PauseAudio (0);
+
+ /*
+ * initializes the timeout mechanism
+ */
+ AD.timer = 1;
+ AD.timeout = timeout;
+
+ /*
+ * controlled delay
+ */
+ audioplayer_delay (timeout);
+
+ return 0;
+}