#include <clib/alib_protos.h>
#include <clib/datatypes_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/iffparse_protos.h>
#include <clib/xpkmaster_protos.h>
#include <datatypes/soundclassext.h>
//#include <libraries/rsnd.h>
#include <stdlib.h>
#include "rsnd.h"

static char *ver="$VER:DT2RSND 41.0 (12.12.98) © 1998 by Achim Stegemann\n";

static char *ifferrmsg[]=
{
0,
0,
0,
"No valid scope for property",
"Internal memory alloc failed",
"Stream read error",
"Stream write error",
"Stream seek error",
"Data in file is corrupt",
"IFF syntax error",
"Not an IFF file",
"No call-back hook provided"
};

static long ifferr,xpkerr,memerr,xpkmode=100;

static char xpkerrmsg[XPKERRMSGSIZE];

struct
{
char *from;
char *to;
char *xpk;
long *xpkmode;
char *password;
long verbose;
} args;

static BOOL PutRSHD(IFFHandle *iff,RSHD *rh)
{
BOOL ret=0;
if(!(ifferr=PushChunk(iff,0,ID_RSHD,sizeof(RSHD))))
	{
	if((ifferr=WriteChunkRecords(iff,rh,sizeof(RSHD),1))==1)
		{
		if(!(ifferr=PopChunk(iff))) ret=1;
		}
	}
return ret;
}

static BOOL WriteSample(Object *obj,IFFHandle *iff,RSHD *rh)
{
BOOL ret=0;
ULONG len,xpklen,outlen;
UBYTE *sample,*xpk;
GetDTAttrs(obj,SDTA_Sample,&sample,SDTA_SampleLength,&len,TAG_END);
len*=(rh->rshd_BitsPerSample>>3)*rh->rshd_NumChannels;
if(!(xpkerr=XpkPackTags(XPK_InBuf,sample,XPK_InLen,len,XPK_GetOutBuf,&xpk,XPK_GetOutBufLen,&xpklen,XPK_GetOutLen,&outlen,XPK_PackMethod,args.xpk,XPK_PackMode,args.xpkmode,XPK_Password,args.password,XPK_GetError,xpkerrmsg,TAG_END)))
	{
	if((ifferr=WriteChunkRecords(iff,xpk,outlen,1))==1) ret=1;
	FreeMem(xpk,xpklen);
	ret=1;
	}
return ret;
}

static BOOL PutBODY(Object *obj,IFFHandle *iff,RSHD *rh)
{
BOOL ret=0;
if(!(ifferr=PushChunk(iff,0,ID_RBOD,IFFSIZE_UNKNOWN)))
	{
	BOOL wok=0;
	if(args.verbose) PutStr("Writing IFF-RSND file ...\n");
	wok=WriteSample(obj,iff,rh);
	if(wok)
		{
		if(!(ifferr=PopChunk(iff))) ret=1;
		}
	}
return ret;
}

void main()
{
ULONG ret=10;
RDArgs *rd;
if(rd=ReadArgs("FROM/A,TO/A,XPK/A/K,MODE/K/N,PASSWORD,VERBOSE/S",(long *)&args,0))
	{
	BOOL ok=0;
	Object *obj;
	if(args.xpkmode)
		{
		xpkmode=*args.xpkmode;
		if(xpkmode<0) xpkmode=0;
		else if(xpkmode>100) xpkmode=100;
		}
	if(args.verbose) Printf("Loading %s ...\n",args.from);
	if(obj=NewDTObject(args.from,DTA_GroupID,GID_SOUND,TAG_END))
		{
		IFFHandle *iff;
		if(iff=AllocIFF())
			{
			if(iff->iff_Stream=Open(args.to,MODE_NEWFILE))
				{
				InitIFFasDOS(iff);
				if(!(ifferr=OpenIFF(iff,IFFF_WRITE)))
					{
					if(!(ifferr=PushChunk(iff,ID_RSND,ID_FORM,IFFSIZE_UNKNOWN)))
						{
						RSHD rh;
						ULONG type;
						GetDTAttrs(obj,SDTA_SampleLength,&rh.rshd_Length,SDTA_Frequency,&rh.rshd_Frequency,SDTA_SampleType,&type,TAG_END);
						rh.rshd_BitsPerSample=((type>>1)+1)*8;
						rh.rshd_NumChannels=(type&1)+1;
						if(PutRSHD(iff,&rh))
							{
							if(PutBODY(obj,iff,&rh))
								{
								if(!(ifferr=PopChunk(iff))) ok=1;
								}
							}
						}
					CloseIFF(iff);
					}
				Close(iff->iff_Stream);
				if(ifferr<-2) Printf("IFF error: %s\n",ifferrmsg[-ifferr]);
				if(xpkerr) Printf("Xpk error: %s\n",xpkerrmsg);
				if(memerr) PutStr("Out of memory.\n");
				if(!ok) DeleteFile(args.to);
				else
					{
					if(args.verbose) PutStr("Conversion finished.\n");
					SetProtection(args.to,FIBF_EXECUTE);
					ret=0;
					}
				}
			FreeIFF(iff);
			}
		else PutStr("AllocIFF failed.\n");
		DisposeDTObject(obj);
		}
	else Printf("Loading of DTObject %s failed.\n",args.from);
	FreeArgs(rd);
	}
if(IoErr()) PrintFault(IoErr(),"DOS error");
exit(ret);
}
