/* ----------------------------------------------------------------------------
 * This file was automatically generated by SWIG (http://www.swig.org).
 * Version 1.3.31
 * 
 * This file is not intended to be easily readable and contains a number of 
 * coding conventions designed to improve portability and efficiency. Do not make
 * changes to this file unless you know what you are doing--modify the SWIG 
 * interface file instead. 
 * ----------------------------------------------------------------------------- */

#include "SDL_sound_wrap.h"
/* -----------------------------------------------------------------------------
 *  This section contains generic SWIG labels for method/variable
 *  declarations/attributes, and other compiler dependent labels.
 * ----------------------------------------------------------------------------- */

/* template workaround for compilers that cannot correctly implement the C++ standard */
#ifndef SWIGTEMPLATEDISAMBIGUATOR
# if defined(__SUNPRO_CC)
#   if (__SUNPRO_CC <= 0x560)
#     define SWIGTEMPLATEDISAMBIGUATOR template
#   else
#     define SWIGTEMPLATEDISAMBIGUATOR 
#   endif
# else
#   define SWIGTEMPLATEDISAMBIGUATOR 
# endif
#endif

/* inline attribute */
#ifndef SWIGINLINE
# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__))
#   define SWIGINLINE inline
# else
#   define SWIGINLINE
# endif
#endif

/* attribute recognised by some compilers to avoid 'unused' warnings */
#ifndef SWIGUNUSED
# if defined(__GNUC__)
#   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
#     define SWIGUNUSED __attribute__ ((__unused__)) 
#   else
#     define SWIGUNUSED
#   endif
# elif defined(__ICC)
#   define SWIGUNUSED __attribute__ ((__unused__)) 
# else
#   define SWIGUNUSED 
# endif
#endif

#ifndef SWIGUNUSEDPARM
# ifdef __cplusplus
#   define SWIGUNUSEDPARM(p)
# else
#   define SWIGUNUSEDPARM(p) p SWIGUNUSED 
# endif
#endif

/* internal SWIG method */
#ifndef SWIGINTERN
# define SWIGINTERN static SWIGUNUSED
#endif

/* internal inline SWIG method */
#ifndef SWIGINTERNINLINE
# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE
#endif

/* exporting methods */
#if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
#  ifndef GCC_HASCLASSVISIBILITY
#    define GCC_HASCLASSVISIBILITY
#  endif
#endif

#ifndef SWIGEXPORT
# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
#   if defined(STATIC_LINKED)
#     define SWIGEXPORT
#   else
#     define SWIGEXPORT __declspec(dllexport)
#   endif
# else
#   if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY)
#     define SWIGEXPORT __attribute__ ((visibility("default")))
#   else
#     define SWIGEXPORT
#   endif
# endif
#endif

/* calling conventions for Windows */
#ifndef SWIGSTDCALL
# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
#   define SWIGSTDCALL __stdcall
# else
#   define SWIGSTDCALL
# endif 
#endif

/* Deal with Microsoft's attempt at deprecating C standard runtime functions */
#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
# define _CRT_SECURE_NO_DEPRECATE
#endif

/*Start of Sound_AudioInfo wrappers*/
DLLPREFIX void _create_Sound_AudioInfo(word occ_args[])
{
	*((void **) occ_args[0]) = (void *) malloc(sizeof(Sound_AudioInfo));
}

DLLPREFIX void _delete_Sound_AudioInfo(word occ_args[])
{
	free(*((void **) occ_args[0]));
}

DLLPREFIX void _get_Sound_AudioInfo_format (word occ_args[])
{
	Sound_AudioInfo *foo = ((Sound_AudioInfo *) occ_args[1]);
	*(INT16(occ_args[0])) = CAST_INT16(foo->format);
}
DLLPREFIX void _set_Sound_AudioInfo_format (word occ_args[])
{
	Sound_AudioInfo *foo = ((Sound_AudioInfo *) occ_args[1]);
	foo->format = (Uint16) VAL_INT16(occ_args[0]);
}
DLLPREFIX void _get_Sound_AudioInfo_channels (word occ_args[])
{
	Sound_AudioInfo *foo = ((Sound_AudioInfo *) occ_args[1]);
	*(BYTE(occ_args[0])) = CAST_BYTE(foo->channels);
}
DLLPREFIX void _set_Sound_AudioInfo_channels (word occ_args[])
{
	Sound_AudioInfo *foo = ((Sound_AudioInfo *) occ_args[1]);
	foo->channels = (Uint8) VAL_BYTE(occ_args[0]);
}
DLLPREFIX void _get_Sound_AudioInfo_rate (word occ_args[])
{
	Sound_AudioInfo *foo = ((Sound_AudioInfo *) occ_args[1]);
	*(INT(occ_args[0])) = CAST_INT(foo->rate);
}
DLLPREFIX void _set_Sound_AudioInfo_rate (word occ_args[])
{
	Sound_AudioInfo *foo = ((Sound_AudioInfo *) occ_args[1]);
	foo->rate = (Uint32) VAL_INT(occ_args[0]);
}
/*End of Sound.AudioInfo wrappers*/

/*Start of Sound_DecoderInfo wrappers*/
DLLPREFIX void _create_Sound_DecoderInfo(word occ_args[])
{
	*((void **) occ_args[0]) = (void *) malloc(sizeof(Sound_DecoderInfo));
}

DLLPREFIX void _delete_Sound_DecoderInfo(word occ_args[])
{
	free(*((void **) occ_args[0]));
}

DLLPREFIX void _get_Sound_DecoderInfo_extensions (word occ_args[])
{
	Sound_DecoderInfo *foo = ((Sound_DecoderInfo *) occ_args[1]);
	*(BYTE(occ_args[0])) = CAST_BYTE(foo->extensions);
}
DLLPREFIX void _set_Sound_DecoderInfo_extensions (word occ_args[])
{
	Sound_DecoderInfo *foo = ((Sound_DecoderInfo *) occ_args[1]);
	foo->extensions = (char const **) VAL_BYTE(occ_args[0]);
}
DLLPREFIX void _get_Sound_DecoderInfo_description (word occ_args[])
{
	Sound_DecoderInfo *foo = ((Sound_DecoderInfo *) occ_args[1]);
	*(BYTE(occ_args[0])) = CAST_BYTE(foo->description);
}
DLLPREFIX void _set_Sound_DecoderInfo_description (word occ_args[])
{
	Sound_DecoderInfo *foo = ((Sound_DecoderInfo *) occ_args[1]);
	foo->description = (char const *) VAL_BYTE(occ_args[0]);
}
DLLPREFIX void _get_Sound_DecoderInfo_author (word occ_args[])
{
	Sound_DecoderInfo *foo = ((Sound_DecoderInfo *) occ_args[1]);
	*(BYTE(occ_args[0])) = CAST_BYTE(foo->author);
}
DLLPREFIX void _set_Sound_DecoderInfo_author (word occ_args[])
{
	Sound_DecoderInfo *foo = ((Sound_DecoderInfo *) occ_args[1]);
	foo->author = (char const *) VAL_BYTE(occ_args[0]);
}
DLLPREFIX void _get_Sound_DecoderInfo_url (word occ_args[])
{
	Sound_DecoderInfo *foo = ((Sound_DecoderInfo *) occ_args[1]);
	*(BYTE(occ_args[0])) = CAST_BYTE(foo->url);
}
DLLPREFIX void _set_Sound_DecoderInfo_url (word occ_args[])
{
	Sound_DecoderInfo *foo = ((Sound_DecoderInfo *) occ_args[1]);
	foo->url = (char const *) VAL_BYTE(occ_args[0]);
}
/*End of Sound.DecoderInfo wrappers*/

/*Start of Sound_Sample wrappers*/
DLLPREFIX void _create_Sound_Sample(word occ_args[])
{
	*((void **) occ_args[0]) = (void *) malloc(sizeof(Sound_Sample));
}

DLLPREFIX void _delete_Sound_Sample(word occ_args[])
{
	free(*((void **) occ_args[0]));
}

DLLPREFIX void _get_Sound_Sample_decoder (word occ_args[])
{
	Sound_Sample *foo = ((Sound_Sample *) occ_args[1]);
	*((void **) occ_args[0]) = (void *) foo->decoder;
}
DLLPREFIX void _get_Sound_Sample_desired (word occ_args[])
{
	Sound_Sample *foo = ((Sound_Sample *) occ_args[1]);
	*((void **) occ_args[0]) = (void *) &foo->desired;
}
DLLPREFIX void _get_Sound_Sample_actual (word occ_args[])
{
	Sound_Sample *foo = ((Sound_Sample *) occ_args[1]);
	*((void **) occ_args[0]) = (void *) &foo->actual;
}
DLLPREFIX void _get_Sound_Sample_buffer (word occ_args[])
{
	Sound_Sample *foo = ((Sound_Sample *) occ_args[1]);
	*(INT(occ_args[0])) = CAST_INT(foo->buffer);
}
DLLPREFIX void _set_Sound_Sample_buffer (word occ_args[])
{
	Sound_Sample *foo = ((Sound_Sample *) occ_args[1]);
	foo->buffer = (void *) VAL_INT(occ_args[0]);
}
DLLPREFIX void _get_Sound_Sample_buffer_size (word occ_args[])
{
	Sound_Sample *foo = ((Sound_Sample *) occ_args[1]);
	*(INT(occ_args[0])) = CAST_INT(foo->buffer_size);
}
DLLPREFIX void _set_Sound_Sample_buffer_size (word occ_args[])
{
	Sound_Sample *foo = ((Sound_Sample *) occ_args[1]);
	foo->buffer_size = (Uint32) VAL_INT(occ_args[0]);
}
DLLPREFIX void _get_Sound_Sample_flags (word occ_args[])
{
	Sound_Sample *foo = ((Sound_Sample *) occ_args[1]);
	*((void **) occ_args[0]) = (void *) &foo->flags;
}
/*End of Sound.Sample wrappers*/

/*Start of Sound_Version wrappers*/
DLLPREFIX void _create_Sound_Version(word occ_args[])
{
	*((void **) occ_args[0]) = (void *) malloc(sizeof(Sound_Version));
}

DLLPREFIX void _delete_Sound_Version(word occ_args[])
{
	free(*((void **) occ_args[0]));
}

DLLPREFIX void _get_Sound_Version_major (word occ_args[])
{
	Sound_Version *foo = ((Sound_Version *) occ_args[1]);
	*(INT(occ_args[0])) = CAST_INT(foo->major);
}
DLLPREFIX void _set_Sound_Version_major (word occ_args[])
{
	Sound_Version *foo = ((Sound_Version *) occ_args[1]);
	foo->major = (int) VAL_INT(occ_args[0]);
}
DLLPREFIX void _get_Sound_Version_minor (word occ_args[])
{
	Sound_Version *foo = ((Sound_Version *) occ_args[1]);
	*(INT(occ_args[0])) = CAST_INT(foo->minor);
}
DLLPREFIX void _set_Sound_Version_minor (word occ_args[])
{
	Sound_Version *foo = ((Sound_Version *) occ_args[1]);
	foo->minor = (int) VAL_INT(occ_args[0]);
}
DLLPREFIX void _get_Sound_Version_patch (word occ_args[])
{
	Sound_Version *foo = ((Sound_Version *) occ_args[1]);
	*(INT(occ_args[0])) = CAST_INT(foo->patch);
}
DLLPREFIX void _set_Sound_Version_patch (word occ_args[])
{
	Sound_Version *foo = ((Sound_Version *) occ_args[1]);
	foo->patch = (int) VAL_INT(occ_args[0]);
}
/*End of Sound.Version wrappers*/

DLLPREFIX void _Sound_GetLinkedVersion (word w[])

{
  Sound_GetLinkedVersion (((Sound_Version*)(*INT(w[0]))));
  return;
}


DLLPREFIX void _Sound_Init (word w[])

{
  *(INT(w[0])) = Sound_Init ();
  return;
}


DLLPREFIX void _Sound_Quit (word w[])

{
  *(INT(w[0])) = Sound_Quit ();
  return;
}


DLLPREFIX void _Sound_AvailableDecoders (word w[])

{
  (*INT(w[0])) = (int) Sound_AvailableDecoders ();
  return;
}



	inline static void occ_Sound_GetError(char err_str[], int err_str_len, int *str_len)
	{
  	char *err = Sound_GetError();

  	*str_len = 0;

  	while(*str_len < err_str_len && err[*str_len] != '\0')
    	err_str[*str_len] = err[(*str_len)++];
		return;
	}

DLLPREFIX void _occ_Sound_GetError (word w[])

{
  occ_Sound_GetError ((BYTE(w[0])), (VAL_INT(w[2])), (INT(w[3])));
  return;
}


DLLPREFIX void _Sound_ClearError ()

{
  Sound_ClearError ();
  return;
}


DLLPREFIX void _Sound_NewSampleFromFile (word w[])

{
  (*INT(w[0])) = (int) Sound_NewSampleFromFile ((BYTE(w[1])), ((Sound_AudioInfo*)(*INT(w[3]))), (VAL_INT(w[4])));
  return;
}


DLLPREFIX void _Sound_FreeSample (word w[])

{
  Sound_FreeSample (((Sound_Sample*)(*INT(w[0]))));
  return;
}


DLLPREFIX void _Sound_SetBufferSize (word w[])

{
  *(INT(w[0])) = Sound_SetBufferSize (((Sound_Sample*)(*INT(w[1]))), (VAL_INT(w[2])));
  return;
}


DLLPREFIX void _Sound_Decode (word w[])

{
  *(INT(w[0])) = Sound_Decode (((Sound_Sample*)(*INT(w[1]))));
  return;
}


DLLPREFIX void _Sound_DecodeAll (word w[])

{
  *(INT(w[0])) = Sound_DecodeAll (((Sound_Sample*)(*INT(w[1]))));
  return;
}


DLLPREFIX void _Sound_Rewind (word w[])

{
  *(INT(w[0])) = Sound_Rewind (((Sound_Sample*)(*INT(w[1]))));
  return;
}


DLLPREFIX void _Sound_Seek (word w[])

{
  *(INT(w[0])) = Sound_Seek (((Sound_Sample*)(*INT(w[1]))), (VAL_INT(w[2])));
  return;
}



/* Global flag determining decode status */
static volatile int global_done_flag = 0;
/*
 * The audio callback. SDL calls this frequently to feed the audio device.
 *  We decode the audio file being played in here in small chunks and feed
 *  the device as necessary. Other solutions may want to predecode more
 *  (or all) of the file, since this needs to run fast and frequently,
 *  but since we're only sitting here and waiting for the file to play,
 *  the only real requirement is that we can decode a given audio file
 *  faster than realtime, which isn't really a problem with any modern format
 *  on even pretty old hardware at this point.
 */
/* Global decode state 
   decoded_ptr is a pointer to where we currently are in the data
   decoded_bytes is the number of bytes left to decode (so kind of misnamed) 
   the first_time flag is set to 1 if it is not the first time this callback
   is being called. */
Uint8 *decoded_ptr = 0;
Uint32 *decoded_bytes = 0;
Uint8 first_time = 0; 

static void audio_callback(void *userdata, Uint8 *stream, int len)
{
   Sound_Sample *sample = (Sound_Sample *) userdata;
   int remaining;
   if(first_time == 0) {  /* First entry into function */
     decoded_ptr = sample->buffer;
     decoded_bytes = sample->buffer_size;
     //printf("First Call of callback: buffer_size %i, len %i  \n", decoded_bytes, len);
     first_time = 1;
   }

   if (decoded_bytes == 0)
   {
     //printf("Done\n");
     /* ...there isn't any more data to read! */
     memset(stream, '\0', len);  /* write silence. */
     global_done_flag = 1;
     return;  /* we're done playback, one way or another. */
   } /* if */
   
   /* Check if we have enough remaining */
   remaining = decoded_bytes - len;
   if(remaining < 0) /* Running out of sound to write */
   {
     //printf("Last few bytes\n");
     /* write this last data to the device. */
     memcpy(stream, (Uint8 *) decoded_ptr, decoded_bytes);
     /* Pad remainder with silence */
     /* Reset state for next file to play - RACE Condition 
        This function will be called a number of times before
        we catch on that its done.  Have to figure out a 
        better way to reset first time so we can play another
        sample.  Well, so that we can play more than one sample
        at a time would be nice too...*/
     //first_time = 0; 
     decoded_ptr = 0;
     decoded_bytes = 0;
   } else {
     //printf("Next load of data %i\n", decoded_bytes);
     /* Copy data to sound device */
     memcpy(stream, (Uint8 *) decoded_ptr, len);
     /* update state for next callback */
     decoded_ptr += len;
     decoded_bytes -= len;
   }
} 

static int get_audio_callback_ptr() {
    return (int)audio_callback;
}

static int check_if_done_playing(){
  return global_done_flag;
}


DLLPREFIX void _get_audio_callback_ptr (word w[])

{
  *(INT(w[0])) = get_audio_callback_ptr ();
  return;
}


DLLPREFIX void _check_if_done_playing (word w[])

{
  *(INT(w[0])) = check_if_done_playing ();
  return;
}


