/* Play.c */

/* Spielt einen Sound ab */

#include "exec/types.h"
#include "exec/memory.h"
#include "devices/audio.h"
#include "lattice/stdio.h"	/* Lattice I/O Definitionen */

#define LEFT0F			1
#define RIGHT0F		2
#define RIGHT1F		4
#define LEFT1F			8

extern struct MsgPort *CreatePort();

/*  Erst nach einem linken, dann nach einem rechten gucken */
UBYTE allocationMap[] = {LEFT0F,LEFT1F,RIGHT0F,RIGHT1F};

struct SHeader {
	ULONG len;
	UWORD rate;
};

main(argc,argv)
int argc;
char *argv[];
{
	struct SHeader *SoundBuf;
	struct IOAudio *id;

	if(argc == 1)
	{
		printf("Syntax: Play <filename>\n");
		return(20);
	}

	/* So, nun gut aufgepasst: */

	if ((SoundBuf = LoadSound(argv[1])) == 0)
	{
		printf("Konnte '%s' leider nicht laden.\n",argv[1]);
		return(21);
	}

	/* So, geladen. Nun im Hintergrund starten */

	if ((id = StartSound(SoundBuf,64,1)) == 0)	/* Lautstaerke 64, 1xspielen */
	{
		printf("Konnte Sound nicht starten.\n");
		return(22);
	}

	/* jetzt koennte ich praktisch machen, was ich will */

	while(!(CheckIO(id)));	/* Ich warte nur, bis vorbei */
	
	StopSound(id);	/* Aus damit */

	FreeSound(SoundBuf); /* und freigeben */

}

/* Benutzung : LoadSound(filename) */
/* filename ist ein Zeiger auf den Namen */
/* buffer ist ein (char *) Zeiger auf den Speicherbereich */
/* Resultat : Zeiger auf Puffer (0=Error) */


LoadSound(fname)	/* SoundFile lesen */
char *fname;	/* Name */
{
	FILE *fp;								/* File Pointer */
	ULONG len;								/* Data Length */
	UWORD rec_rate;
	struct SHeader *buffer;							/* Record Rate (kHz) */

	/* Zum Lesen oeffnen */
	if ((fp = fopen(fname,"r")) == 0) return(0);

	/* Laenge lesen */
	if(fread(&len,sizeof(len),1,fp) == 0)
	{
		fclose(fp);
		return(0);
	}

	/* Record-Rate lesen */
	if(fread(&rec_rate,sizeof(rec_rate),1,fp) == 0)
	{
		fclose(fp);
		return(0);
	}

	/* Alles klar: Speicher holen (CHIP!!!) */

	if((buffer=(struct SHeader *)AllocMem(len+6,MEMF_CHIP)) == 0)
	{
		fclose(fp);
		return(0);
	}

	buffer->len  = len;
	buffer->rate = rec_rate;
	
	/* Daten lesen */
	if(fread(buffer+1,len,1,fp) == 0) /* Diesmal ist buffer ein Byte-Array */

	{
		fclose(fp);
		FreeSound(buffer);
		return(0);
	}

	/* Zumachen */
	fclose(fp);

	/* Zeiger zurueckgeben */
	return(buffer);
}

FreeSound(buffer)
struct SHeader *buffer;
{
	FreeMem(buffer,(buffer->len)+6);
}

/* Diese Routine spielt einen Sound ab */

/* Benutzung: 1)  ioaudio = StartSound(buffer,volume,numrepeat) */
/*            2)  success = StopSound(ioaudio) */

/* Achtung! Sound darf nicht laenger als 131072 Bytes sein! */


/* IO-Request initialisieren */
SetIOA(rate,vol,repeat,buf,len,ioa)
int rate,vol,repeat;
ULONG len;
struct SHeader *buf;
struct IOAudio **ioa;
{
	struct MsgPort *port;
	char *PortName;

	PortName = "DSOUND";

	/* IO-Request holen */
	(*ioa) = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
									    MEMF_PUBLIC|MEMF_CLEAR);
	if((*ioa)!=0)
	{
		(*ioa)->ioa_Request.io_Message.mn_Node.ln_Pri = 10;
		if ((port = CreatePort(PortName,0)) == 0)
		{
			FreeMem((*ioa),sizeof(struct IOAudio));
			/* War nix */
		}
		else
		{
			/* Audio-Kanal holen */
			(*ioa)->ioa_Request.io_Message.mn_ReplyPort = port;
			(*ioa)->ioa_Data = allocationMap;
			(*ioa)->ioa_Length = sizeof(allocationMap);
			/* Audio Device oeffnen */
			if(OpenDevice(AUDIONAME,0,(*ioa),0) != 0)
			{
				/* war nix */
				DeletePort(port);
				FreeMem((*ioa),sizeof(struct IOAudio));
			}
			else
			{
				/* Request initialisieren */
				(*ioa)->ioa_Request.io_Flags = ADIOF_PERVOL;
				(*ioa)->ioa_Request.io_Command = CMD_WRITE;
				(*ioa)->ioa_Period = 3579545/rate;
				(*ioa)->ioa_Volume = vol;
				(*ioa)->ioa_Length = len;
				(*ioa)->ioa_Data = buf;

				(*ioa)->ioa_Cycles = repeat;
			}
		}
	}
}

/* ================================================================ */

/* Dies ist die eigentliche Routine */


StartSound(buffer,vol,numrep)
struct SHeader *buffer;
int numrep,vol;
{
	struct IOAudio *ioa;
	BYTE *DataPtr;
	ULONG PlayLen=0;
	UWORD rate;

	if((PlayLen = buffer->len) > 131072) return (0);
	rate = buffer->rate;
	DataPtr = buffer+1;	/* 1 struct SHeader */

	/* IO-Request initialisieren */
	SetIOA(rate,vol,numrep,DataPtr,PlayLen,&ioa);

	/* Starten */
	BeginIO(ioa);

	/* Und Zeiger returnen */
	return (ioa);
}

StopSound(ioa)
struct IOAudio *ioa;
{
	AbortIO(ioa);	/* Halt!!! */
	if(ioa->ioa_Request.io_Device)
	{
		CloseDevice(ioa);
	}
	if(ioa->ioa_Request.io_Message.mn_ReplyPort)
	{
		DeletePort(ioa->ioa_Request.io_Message.mn_ReplyPort);
	}
	if(ioa)
	{
		FreeMem(ioa,sizeof(struct IOAudio));
	}
}



