/*
*    ___                       ____                  __
*   / _ \___ _    _____ ____  / __/__  __ _____  ___/ /
*  / ___/ _ \ |/|/ / -_) __/ _\ \/ _ \/ // / _ \/ _  /
* /_/   \___/__,__/\__/_/   /___/\___/\_,_/_//_/\_,_/
*
*
*   Original Code by Max Watson
*   Written November 1, 1999
*   To be released under the LGPL
*
*   PowerSound audio mixer declarations
*   Mostly taken from the SDL-demo mixer library
*   borrowed by Max Watson <max@blackholesun.com>
*/

#ifndef _PS_H
#define _PS_H

#include <SDL/SDL_types.h>
#include <SDL/SDL_rwops.h>
#include <SDL/SDL_audio.h>

#ifdef __cplusplus
extern "C" {
#endif

/* The default mixer has 4 simultaneous mixing channels */
#ifndef PS_MIX_CHANNELS
#define PS_MIX_CHANNELS 4
#endif

/* Good default values for a PC soundcard */
#define PS_DEFAULT_FREQ      22050
#define PS_DEFAULT_FORMAT    AUDIO_S16
#define PS_DEFAULT_CHANNELS  2
#define PS_DEFAULT_CHUNKSIZE 2048

#define PS_MAX_VOLUME        128

#define PS_GetError SDL_GetError
#define PS_SetError SDL_SetError

/* The format for an audio sample */
typedef struct
{
    Uint8 *abuf;       // pointer to sample data
    Uint32 alen;       // length of sample
    int volume;        // per-sample volume
    int pan;           // Pan range -128 (left) to 0 (center) to 128 (right)
    int depth;         // Depth range -128 (behind) to 0 (center) to 128 (forward)
} PS_Sample;

/* format for an mixer channel */
typedef struct _PS_Channel {
    PS_Sample *chunk;
    int playing;       
    Uint8 *samples;    
    int lvol;
    int rvol;
    int looping;
} PS_Channel;

extern int PS_Init(void);
extern int PS_Quit(void);

// Master Volume control
#define PS_Volume(volume)  PS_ChannelVolume(-1, volume)

/*
 * Open/Close/Query the audio device
 */

// Open the audio device with the specified format.
extern int  PS_AudioOpen(int frequency, Uint16 format,
                         int channels, int chunksize);


extern int  PS_AudioOpenWithCallback(int frequency, Uint16 format,
                         int channels, int chunksize, void *callback);

// Close the audio device, halting all playing audio
extern void PS_AudioClose(void);

// Find out what the actual audio device parameters are.
// This function returns 1 if the audio has been opened, 0 otherwise.
extern int  PS_AudioQuery(int *frequency, Uint16 *format, Uint8 *channels);

/*
 * Mixer channel controls
 */

// Check the status of a specific channel.
// If the specified channel is -1, check all channels.
extern int  PS_ChannelPlaying(int which);

// Halt playing of a particular channel
// If the specified channel is -1, halt all channels.
extern int  PS_ChannelHalt(int which);

// Set the volume in the range of 0-128 of a specific channel.
// If the specified channel is -1, set volume for all channels.
// Returns the original volume.
// If the specified volume is -1, just return the current volume.
extern int  PS_ChannelVolume(int which, int volume);

// Returns a pointer to the sample currently playing on the
// specified channel. Returns NULL if no sound is playing.
extern PS_Sample* PS_ChannelSampleGet(int which);

/*
 * Routine to manipulate audio samples
 */

// Load a sound sample from a wave file
extern PS_Sample* PS_SampleLoad(const char *file);

// Free a previously loaded sample
extern void PS_SampleFree(PS_Sample *sample);

// Pan ranges from -128 (left) to 0 (center) to 128 (right)
// Depth ranges from -128 (behind) to 0 (center) to 128 (ahead)

// Return the pan of the audio sample
extern int  PS_SamplePanGet(PS_Sample *sample);

// Set the pan [-128,128] for the given sample
extern void PS_SamplePanSet(PS_Sample *sample, int pan);

// Return the depth of the audio sample
extern int  PS_SampleDepthGet(PS_Sample *sample);

// Set the depth [-128,128] for the given sample
extern void PS_SampleDepthSet(PS_Sample *sample, int depth);

// Set the volume [0,128] for the given sample
extern void PS_SampleVolume(PS_Sample *sample,  int volume);

// Play an audio sample on a specific channel.
// If the specified channel is -1, play on the first free channel.
// If 'loops' is greater than zero, loop the sound that many times.
// If 'loops' is -1, loop inifinitely (~65000 times).
// Returns which channel was used to play the sound.
extern int  PS_SamplePlayOnChannel(int channel, PS_Sample *sample,
                                   int loops);

// Similar to the previous function with 3D positioning
// pan =   left   <-> right
// depth = behind <-> ahead
extern int  PS_SamplePlay3DOnChannel(int channel, PS_Sample *sample,
                                   int pan, int depth, int loops);

void PS_AudioLock();
void PS_AudioUnlock();
void PS_AudioPause(int onoff);

// Convenience macros to quickly play a sample
#define     PS_SamplePlay(sample)              PS_SamplePlayOnChannel(-1, sample, 0)
#define     PS_SamplePlay3D(sample, pan, depth)  PS_SamplePlay3DOnChannel(-1, sample, pan, depth, 0)

#ifdef __cplusplus
};
#endif

#endif
