/*
 * beep.c
 *
 * Ultra-simple beep, for keyclick.c
 * MWS, 5/92.
 *
 * Hacked from audio1.c (RKM companion disks)...
 * ...Copyright (c) 1990 Commodore-Amiga, Inc.
 */
#include <exec/types.h>		/* Some header files for system calls */
#include <exec/memory.h>
#include <devices/audio.h>
#include <graphics/gfxbase.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include "beep.h"		/* prototypes */

static UBYTE whichannel[] = {1, 2, 4, 8};
static struct IOAudio *AIOptr;	/* Pointer to the IO block for IO commands   */
static struct MsgPort *port;	/* Pointer to a port so the device can reply */

UBYTE __chip data[] = {
	0xEF, 0xFB, 0xF7, 0xF7, 0x12, 0x0F, 0xDA, 0xCC, 
	0x06, 0x20, 0x2A, 0x07, 0xC7, 0xB8, 0xD7, 0x15, 
	0x50, 0x38, 0xF4, 0xB1, 0x86, 0xD0, 0x24, 0x4D, 
	0x27, 0xEB, 0xBC, 0xAE, 0xD5, 0x0B, 0x1E, 0x08, 
	0xDE, 0xC1, 0xC9, 0xF4, 0x28, 0x2C, 0x07, 0xDE, 
	0xC3, 0xC6, 0xE4, 0x10, 0x20, 0x04, 0xE3, 0xD1, 
	0xD9, 0xEE, 0x13, 0x24, 0x15, 0xEC, 0xD1, 0xCC, 
	0xE4, 0x0B, 0x1E, 0x18, 0xF8, 0xDE, 0xD7, 0xE5, 
	0xFD, 0x13, 0x1A, 0x06, 0xE9, 0xDA, 0xE1, 0xF4, 
	0x08, 0x17, 0x16, 0xFB, 0xE1, 0xD4, 0xE4, 0xFD, 
	0x0E, 0x15, 0x0C, 0xF1, 0xDE, 0xE0, 0xF0, 0x00
};

#define SAMPLES		sizeof(data)
#define DURATION	5
#define FREQUENCY	270

long clock = 3579545;	/* default to PAL if no GfxBase */
extern struct GfxBase	*GfxBase;

void
FreeAudio ()			/* free allocated audio resources */
{
	if (AIOptr)
	{
		FreeMem (AIOptr, sizeof (struct IOAudio));
		AIOptr = NULL;
	}
	if (port)
	{
		DeleteMsgPort (port);
		port = NULL;
	}
}

BOOL 
AllocAudio ()			/* allocate audio resources */
{
	if (GfxBase = (void *)OpenLibrary("graphics.library", 0L))
	{
		if (GfxBase->DisplayFlags & PAL)
			clock = 3456895;
		CloseLibrary(GfxBase);
	}

	if ((AIOptr = (void *)AllocMem (sizeof (struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR)) &&
	    (port = CreateMsgPort ()))
	{
		AIOptr->ioa_Request.io_Message.mn_ReplyPort = port;
		AIOptr->ioa_Request.io_Message.mn_Node.ln_Pri = 0;
		return TRUE;
	}
	FreeAudio ();
	return FALSE;
}

void
beep (long volume)
{
	static struct Message *msg;	/* Pointer for the reply message             */

	AIOptr->ioa_Request.io_Command = ADCMD_ALLOCATE;
	AIOptr->ioa_Request.io_Flags = ADIOF_NOWAIT;
	AIOptr->ioa_AllocKey = 85;
	AIOptr->ioa_Data = whichannel;
	AIOptr->ioa_Length = sizeof (whichannel);

	/** Open the audio device and allocate a channel **/
	if (OpenDevice ("audio.device", 0L, (struct IORequest *) AIOptr, 0L))
		return;

	AIOptr->ioa_Request.io_Command = CMD_WRITE;
	AIOptr->ioa_Request.io_Flags = ADIOF_PERVOL;
	AIOptr->ioa_Data = (BYTE *)data;
	AIOptr->ioa_Length = SAMPLES;
	AIOptr->ioa_Period = clock / (SAMPLES * FREQUENCY);
	AIOptr->ioa_Cycles = (FREQUENCY * DURATION) / 1000;
	AIOptr->ioa_Volume = volume;

	BeginIO ((struct IORequest *) AIOptr);
	Wait (1L << port->mp_SigBit);
	msg = GetMsg (port);

	CloseDevice ((struct IORequest *) AIOptr);
}
