/*******************************************************************************
 *
 * (c) Copyright 1993 Commodore-Amiga, Inc.  All rights reserved.
 *
 * This software is provided as-is and is subject to change; no warranties
 * are made.  All use is at your own risk.  No liability or responsibility
 * is assumed.
 *
 * audio.c - uses the audio.device to initialise and play all the audio.
 *
 ******************************************************************************/

#include <exec/execbase.h>
#include <graphics/gfxbase.h>
#include <devices/audio.h>
#include <proto/exec.h>
#include "stick.h"
#include "playanim.h"

extern struct GfxBase *GfxBase;
extern struct ExecBase *SysBase;

void ThrustAudio(struct IOAudio *ThrustAudioIO[], struct RawAudio *RawAudio, UBYTE *ThrustBuffer)
{
    ThrustAudioIO[0]->ioa_Request.io_Command = CMD_WRITE;
    ThrustAudioIO[0]->ioa_Request.io_Flags = ADIOF_PERVOL;
    ThrustAudioIO[0]->ioa_Data = ThrustBuffer;
    ThrustAudioIO[0]->ioa_Length = RawAudio->ra_SizeOfSample;
    ThrustAudioIO[0]->ioa_Period = PERIOD(RawAudio->ra_SamplesPerSecond);
    ThrustAudioIO[0]->ioa_Volume = VOLUME(RawAudio->ra_Volume);
    ThrustAudioIO[0]->ioa_Cycles = 0;	/* infinite */

    ThrustAudioIO[1]->ioa_Request.io_Command = CMD_WRITE;
    ThrustAudioIO[1]->ioa_Request.io_Flags = ADIOF_PERVOL;
    ThrustAudioIO[1]->ioa_Data = ThrustBuffer;
    ThrustAudioIO[1]->ioa_Length = RawAudio->ra_SizeOfSample;

    /* For stereo effect, modify the period of the other channel slightly. This
     * number just happens to be good for the audio I used.
     */

    ThrustAudioIO[1]->ioa_Period = (PERIOD(RawAudio->ra_SamplesPerSecond) - 27);
    ThrustAudioIO[1]->ioa_Volume = VOLUME(RawAudio->ra_Volume);
    ThrustAudioIO[1]->ioa_Cycles = 0;	/* infinite */

    BeginIO((struct IORequest *)ThrustAudioIO[0]);
    BeginIO((struct IORequest *)ThrustAudioIO[1]);
}

void FireAudio(struct Input *input)
{
    struct InputAudio *ia = &input->FireAudio;
    struct IOAudio *ioa = ia->AudioIO;

    if (ia->Playing)
    {
	/* interrupt the audio already playing, to give a 'rapid fire' effect. */
	GetMsg(ia->AudioMP);
	ioa->ioa_Request.io_Command = ADCMD_FINISH;
	ioa->ioa_Request.io_Flags = IOF_QUICK;
	ioa->ioa_Request.io_Unit = (struct Unit *)ia->Unit;
	ioa->ioa_AllocKey = ia->AllocKey;
	BeginIO((struct IORequest *)ioa);
	ia->Playing = FALSE;
    }

    ioa->ioa_Request.io_Command = CMD_WRITE;
    ioa->ioa_Request.io_Flags = ADIOF_PERVOL;
    ioa->ioa_Request.io_Unit = (struct Unit *)ia->Unit;
    ioa->ioa_AllocKey = ia->AllocKey;
    ioa->ioa_Data = ia->AudioBuffer;
    ioa->ioa_Length = ia->RawAudio->ra_SizeOfSample;
    ioa->ioa_Period = ia->Period;
    ioa->ioa_Volume = VOLUME(ia->RawAudio->ra_Volume);
    ioa->ioa_Cycles = 1;
    BeginIO((struct IORequest *)ioa);
    ia->Playing = TRUE;
}

ULONG InitAudio(struct IOAudio *FireAudioIO, struct IOAudio *ThrustAudioIO[])
{
    UBYTE FireAudioUnits[] = {1, 2, 4, 8};
    /* Build the units required for stereo thruster audio, depending on the Audio
     * channel given to the Fire audio.
     */
    UBYTE ThrustAudioUnits[][] = {{0, 0}, {0x2, 0x8}, {0x1, 0x4}, {0, 0}, {0x2, 0x1}, {0, 0}, {0, 0}, {0, 0}, {0x2, 0x1}};
    ULONG FireUnit;
    ULONG i;

    FireAudioIO->ioa_Data = FireAudioUnits;
    FireAudioIO->ioa_Length = 4;
    FireAudioIO->ioa_Request.io_Command = ADCMD_ALLOCATE;
    FireAudioIO->ioa_Request.io_Flags = 0;
    FireAudioIO->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
    BeginIO((struct IORequest *)FireAudioIO);
    WaitPort(FireAudioIO->ioa_Request.io_Message.mn_ReplyPort);
    GetMsg(FireAudioIO->ioa_Request.io_Message.mn_ReplyPort);
    if (FireAudioIO->ioa_Request.io_Error != 0)
    {
	return(1);	/* show that Fire audio not allocated */
    }

    for (i = 0; i < 2; i++)
    {
	FireUnit = (ULONG)FireAudioIO->ioa_Request.io_Unit;
	ThrustAudioIO[i]->ioa_Data = &(ThrustAudioUnits[FireUnit][i]);
	ThrustAudioIO[i]->ioa_Length = 1;
	ThrustAudioIO[i]->ioa_Request.io_Command = ADCMD_ALLOCATE;
	ThrustAudioIO[i]->ioa_Request.io_Flags = 0;
	ThrustAudioIO[i]->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
	BeginIO((struct IORequest *)ThrustAudioIO[i]);
	WaitPort(ThrustAudioIO[i]->ioa_Request.io_Message.mn_ReplyPort);
	GetMsg(ThrustAudioIO[i]->ioa_Request.io_Message.mn_ReplyPort);
	if (ThrustAudioIO[i]->ioa_Request.io_Error != 0)
	{
		return(2 + i);	/* show that Thrust audio not allocated */
	}
    }

    /* The caller may want to produce an error message to say which channel
     * could not be allocated, hence the different error numbers returned.
     */
    return(0);
}
