/*
*    ___                       ____                  __
*   / _ \___ _    _____ ____  / __/__  __ _____  ___/ /
*  / ___/ _ \ |/|/ / -_) __/ _\ \/ _ \/ // / _ \/ _  /
* /_/   \___/__,__/\__/_/   /___/\___/\_,_/_//_/\_,_/
*
*
*   Original Code by Max Watson
*   Written November 1, 1999
*   To be released under the LGPL
*
*   PowerSound audio channel control functions
*   Mostly taken from the SDL-demo mixer library
*   borrowed (with changes) by Max Watson <max@blackholesun.com>
*
*   See LICENSE.TXT for more LGPL info
*/

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include "SDL/SDL_audio.h"
#include "SDL/SDL_mutex.h"
#include "SDL/SDL_timer.h"

#include "powersound.h"

SDL_AudioSpec mixer;
SDL_mutex *mixer_lock;
PS_Channel channel[PS_MIX_CHANNELS];

// internal audio data mixer - from audio.c
extern void PS_AudioMix (Uint8 *dst, Uint8 *src, Uint32 len,
                         int lvol, int rvol);

int PS_ChannelVolume(int which, int volume)
{
    int i;

    if(which = -1)
        for(i=0; i<PS_MIX_CHANNELS; i++)
            PS_ChannelVolume(i, volume);
    else
    {
        i = channel[which].lvol;
        channel[which].lvol = channel[which].rvol = volume;
        return i;
    }
    return volume;
}

int PS_ChannelPlaying(int which)
{
    int status;

    status = 0;
    if ( which == -1 ) {
        int i;

        for ( i=0; i<PS_MIX_CHANNELS; ++i ) {
            if ( channel[i].playing > 0 ) {
                ++status;
            }
        }
    } else {
        if ( channel[which].playing > 0 ) {
            ++status;
        }
    }
    return(status);
}

int PS_ChannelHalt(int which)
{
    int i;

    if ( which == -1 ) {
        for ( i=0; i<PS_MIX_CHANNELS; ++i ) {
            PS_ChannelHalt(i);
        }
    } else {
        SDL_mutexP(mixer_lock);
        channel[which].playing = 0;
        SDL_mutexV(mixer_lock);
    }
    return(0);
}

/* Mixing function */
void PS_ChannelsMix(void *udata, Uint8 *stream, int len)
{
    int i, mixable,
    lvol, rvol,
    clvol, crvol,
    pan, depth;

    /* Grab the channels we need to mix */
    SDL_mutexP(mixer_lock);
    for ( i=0; i<PS_MIX_CHANNELS; ++i ) {
        if ( channel[i].playing ) {
            mixable = channel[i].playing;
            if ( mixable > len ) {
                mixable = len;
            }

            //Adjust volume for pan and depth
            clvol = channel[i].chunk->volume;
            crvol = channel[i].chunk->volume;
            pan = channel[i].chunk->pan;
            depth = channel[i].chunk->depth;
            if( pan < 0) {
                crvol = ((crvol < -pan) ? 0 : (crvol+pan) );
            }
            else {
                clvol = ((clvol <  pan) ? 0 : (clvol-pan) );
            }
            if( depth < 0) {
                crvol = ((crvol < -depth) ? 0 : (crvol+depth) );
                clvol = ((clvol < -depth) ? 0 : (clvol+depth) );
            }
            else {
                crvol = ((crvol <  depth) ? 0 : (crvol-depth) );
                clvol = ((clvol <  depth) ? 0 : (clvol-depth) );
            }
            lvol = 1+(channel[i].lvol*clvol) / PS_MAX_VOLUME;
            rvol = 1+(channel[i].rvol*crvol) / PS_MAX_VOLUME;

            PS_AudioMix(stream,channel[i].samples,mixable,lvol,rvol);
            channel[i].samples += mixable;
            channel[i].playing -= mixable;
            if ( ! channel[i].playing && channel[i].looping ) {
                if ( --channel[i].looping ) {
                    channel[i].samples = channel[i].chunk->abuf;
                    channel[i].playing = channel[i].chunk->alen;
                }
            }
        }
    }
    SDL_mutexV(mixer_lock);

}
