/* This file contains empty template routines that
 * the IDCMP handler will call uppon. Fill out these
 * routines with your code or use them as a reference
 * to create your program.
 */

#include <exec/types.h>
#include <datatypes/soundclass.h>
#include <graphics/gfxbase.h>
#include <devices/audio.h>
#include <libraries/asl.h>
#include <string.h>
#include <m68881.h>
#include <stdio.h>
#include <math.h>
#include "SVXTool.h"

#include <proto/intuition.h>
#include <proto/gadtools.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/asl.h>

UBYTE __chip playbuffer[2][10240]; // 2 10k play buffers

extern struct GfxBase *GfxBase;
extern struct VoiceHeader Current;
extern struct FileRequester *FReq;
extern UBYTE *Data;
extern char WorkInputFile[256],WorkInputName[31],memtype;
extern int WorkInputLen,WorkInputSPS;

extern void NotifyofError(char *bodytxt);
extern BOOL ReadInputFile(void);

static long FillPBuffer(UBYTE *db,long rlen,struct IOAudio *IOA);

int Hear_BTNClicked( void )
{
	/* routine when gadget "Hear" is clicked. */
	struct MsgPort *audrep[2];
	struct IOAudio *IOA[2];

	UBYTE unitarray[4]={12,10,5,3}; // four tries for a left and right

	if(!(audrep[0]=CreateMsgPort()))
		NotifyofError("Could not open message port for Audio I/O.");
	if(!(audrep[1]=CreateMsgPort()))
		NotifyofError("Could not open message port for Audio I/O.");
	if(audrep[0]&&audrep[1])
	{
		if(!(IOA[0]=CreateIORequest(audrep[0],sizeof(struct IOAudio))))
			NotifyofError("Could not create an I/O request structure.");
		
		if(!(IOA[1]=CreateIORequest(audrep[1],sizeof(struct IOAudio))))
			NotifyofError("Could not create an I/O request structure.");
		if(IOA[0]&&IOA[1])
		{
			long error;

			IOA[0]->ioa_Request.io_Message.mn_Node.ln_Pri=0;
			IOA[0]->ioa_AllocKey=0;
			IOA[0]->ioa_Data=unitarray;
			IOA[0]->ioa_Length=4;
			if(!(error=OpenDevice(AUDIONAME,0,(struct IORequest *)IOA[0],0)))
			{
				UBYTE *PlayPTR;
				long rlen;

				PlayPTR=Data;
				rlen=WorkInputLen;
				IOA[0]->ioa_Request.io_Message.mn_Node.ln_Pri=20;
				IOA[0]->ioa_Request.io_Command=CMD_WRITE;
				IOA[0]->ioa_Request.io_Flags=ADIOF_PERVOL;
				IOA[0]->ioa_Data=playbuffer[0];
				IOA[0]->ioa_Volume=64;
				IOA[0]->ioa_Cycles=1;
				IOA[1]->ioa_Request.io_Message.mn_Node.ln_Pri=20;
				IOA[1]->ioa_Request.io_Command=CMD_WRITE;
				IOA[1]->ioa_Request.io_Flags=ADIOF_PERVOL;
				IOA[1]->ioa_Request.io_Device=IOA[0]->ioa_Request.io_Device;
				IOA[1]->ioa_AllocKey=IOA[0]->ioa_AllocKey;
				IOA[1]->ioa_Data=playbuffer[1];
				IOA[1]->ioa_Volume=64;
				IOA[1]->ioa_Cycles=1;
				IOA[1]->ioa_Request.io_Unit=IOA[0]->ioa_Request.io_Unit;

// possible use sysbase->PowerSupplyFrequency or sysbase->VBlankFrequency as well
// values of 60 for NTSC 50 for PAL

				if(GfxBase->DisplayFlags&PAL)
				{
					IOA[0]->ioa_Period=3546895/WorkInputSPS;
					IOA[1]->ioa_Period=3546895/WorkInputSPS;
				}
				else
				{
					IOA[0]->ioa_Period=3579545/WorkInputSPS;
					IOA[1]->ioa_Period=3579545/WorkInputSPS;
				}
				while(rlen)
				{
					long slen;

					slen=FillPBuffer(PlayPTR,rlen,IOA[0]);
					rlen-=slen;
					if(PlayPTR!=Data)
						WaitIO((struct IORequest *)IOA[1]);
					BeginIO((struct IORequest *)IOA[0]);
					PlayPTR+=slen;
					if(rlen)
					{
						slen=FillPBuffer(PlayPTR,rlen,IOA[1]);
						rlen-=slen;
						PlayPTR+=slen;
						WaitIO((struct IORequest *)IOA[0]);
						BeginIO((struct IORequest *)IOA[1]);
						if(!rlen)
							WaitIO((struct IORequest *)IOA[1]);
					}
					else WaitIO((struct IORequest *)IOA[0]);
				}
				CloseDevice((struct IORequest *)IOA[0]);
			}
			else
			{
				char *errmsg[12]=
				{
					"I/O device/unit failed to open","I/O request aborted",
					"I/O Command not supported","Invalid I/O length",
					"I/O invalid address","I/O device ok, unit is busy",
					"I/O hardware failed self test","undef error",
					"undef error","Audio I/O: no allocation",
					"Audio I/O: allocation failed","Audio I/O: channel stolen"
				};

				NotifyofError(errmsg[-error-1]);
			}
		}
		if(IOA[0])
			DeleteIORequest(IOA[0]);
		if(IOA[1])
			DeleteIORequest(IOA[1]);
	}
	if(audrep[0])
		DeleteMsgPort(audrep[0]);
	if(audrep[1])
		DeleteMsgPort(audrep[1]);
	return(1);
}

int Convert_BTNClicked( void )
{
	/* routine when gadget "Convert" is clicked. */
	char OutName[256],OName[32];
	BPTR OFile;
	char *f,*t,*e;

	for(f=WorkInputFile,t=OutName,e=FilePart(WorkInputFile);f!=e;f++,t++)
		*t=*f;
	*t=0;
	if(GetString(SVXTool_MainGadgets[GDX_SymbolName_STR])[0])
	{
		sprintf(OName,"%s.o",GetString(SVXTool_MainGadgets[GDX_SymbolName_STR]));
		AddPart(OutName,OName,255);
		sprintf(OName,"_%s",GetString(SVXTool_MainGadgets[GDX_SymbolName_STR]));
	}
	else
	{
		sprintf(OName,"%s.o",WorkInputName);
		AddPart(OutName,OName,255);
		sprintf(OName,"_%s",WorkInputName);
	}
	if(OFile=Open(OutName,MODE_OLDFILE))
	{
		struct EasyStruct errorES =
		{
			sizeof(struct EasyStruct),0,
			"SVXTool Message",
			"%s already exists.","Overwrite|Cancel"
		};

		Close(OFile);

		OFile=(BPTR)EasyRequestArgs(SVXTool_MainWnd,&errorES,NULL,OutName);
	}
	if(!OFile)
	{
		if(OFile=Open(OutName,MODE_NEWFILE))
		{
/* write the object file */

			int n;
			long zl=0x00000000;
			long mt[3]={0x00000000,0x40000000,0x80000000};
			long tophunk[8]=
			{
				0x000003E7,0x00000000,
				0x000003E8,0x00000002,0x64617461,0x73656300,
				0x000003EA,0x00000000
			};
			long midhunk[2]={0x000003EF,0x01000000};
			long bothunk[3]=
			{
				0x00000000,0x00000000,
				0x000003F2
			};

			tophunk[6]|=mt[memtype];
			tophunk[7]=(WorkInputLen+4)>>2;
			midhunk[1]|=(strlen(OName)+4)>>2;
			Write(OFile,tophunk,8*sizeof(long));
			Write(OFile,Data,((WorkInputLen+4)>>2)<<2);
			Write(OFile,midhunk,2*sizeof(long));
			Write(OFile,OName,strlen(OName));
			if(n=(((strlen(OName)+4)>>2)<<2)-strlen(OName))
				Write(OFile,&zl,n);
			Write(OFile,bothunk,3*sizeof(long));
			Close(OFile);
		}
		else
			NotifyofError("Could not open output file.");
	}
	return(1);
}

int Input_GFClicked( void )
{
	/* routine when gadget "" is clicked. */
	long e;

	if(AslRequest(FReq,NULL))
	{
		strcpy(WorkInputName,FReq->fr_File);
		strcpy(WorkInputFile,FReq->fr_Drawer);
		AddPart(WorkInputFile,WorkInputName,255);
		if(!ReadInputFile())
		{
			char msg[256];

			sprintf(msg,"Could not find file\n\"%s\".",WorkInputFile);
			NotifyofError(msg);
		}
	}
	else if(e=IoErr())
	{
		char msg[256];

		Fault(e,"I/O Error: ",msg,255);
		NotifyofError(msg);
	}
	return(1);
}

int SymbolName_STRClicked( void )
{
	/* routine when gadget "Symbol Name" is clicked. */
	char *s,*p=GetString(SVXTool_MainGadgets[GDX_SymbolName_STR]);

	for(s=p;*p;p++)
		if(*p==32) *p='_';
	GT_SetGadgetAttrs(SVXTool_MainGadgets[GDX_SymbolName_STR],SVXTool_MainWnd,NULL,GTST_String,s,TAG_END);
	return(1);
}

int memtype_CYCClicked( void )
{
	/* routine when gadget "Mem type" is clicked. */
	memtype=SVXTool_MainMsg.Code;
	return(1);
}

int SVXTool_MainItem0( void )
{
	/* routine when (sub)item "About" is selected. */
	return(1);
}

int SVXTool_MainItem1( void )
{
	/* routine when (sub)item "Quit" is selected. */
	return(0);
}

int SVXTool_MainCloseWindow( void )
{
	/* routine for "IDCMP_CLOSEWINDOW". */
	return(0);
}

static long FillPBuffer(UBYTE *db,long rlen,struct IOAudio *IOA)
{
	long slen;

	slen=min(10240,rlen);
	CopyMem((char *)db,(char *)IOA->ioa_Data,slen);
	IOA->ioa_Length=slen;
	return(slen);
}
