/*
	Skeleton for Player class
*/
#include <StorageKit.h>
#include <InterfaceKit.h>
#include <MediaKit.h>
#include "Player.h"
#include "st.h"
#include "libst.h"

#define PLAYER_NAME "SOXPlayer V1.00"

class PrefsView;

int wavstartread(ft_t ft);
int wavread(ft_t ft, long *buf, int len);
wavstopread(ft_t ft);


int rawread(ft_t ft, long *buf, int nsamp) 
{
	register long datum;
	int done = 0;

	switch(ft->info.size) {
		case BYTE: switch(ft->info.style) {
			case SIGN2:
				while(done < nsamp) {
					datum = getc(ft->fp);
					if (feof(ft->fp))
						return done;
					/* scale signed up to long's range */
					*buf++ = LEFT(datum, 24);
					done++;
				}
				return done;
			case UNSIGNED:
				while(done < nsamp) {
					datum = getc(ft->fp);
					if (feof(ft->fp))
						return done;
					/* Convert to signed */
					datum ^= 128;
					/* scale signed up to long's range */
					*buf++ = LEFT(datum, 24);
					done++;
				}
				return done;
			case ULAW:
				while(done < nsamp) {
					datum = getc(ft->fp);
					if (feof(ft->fp))
						return done;
					datum = st_ulaw_to_linear(datum);
					/* scale signed up to long's range */
					*buf++ = LEFT(datum, 16);
					done++;
				}
				return done;
			case ALAW:
				while(done < nsamp) {
				        datum = getc(ft->fp);
				        if (feof(ft->fp))
				                return done;
				        datum = st_Alaw_to_linear(datum);
				        /* scale signed up to long's range */
				        *buf++ = LEFT(datum, 16);
				        done++;
				}

				return done;
			}
		case WORD: switch(ft->info.style) {
			case SIGN2:
				while(done < nsamp) {
					datum = rshort(ft);
					if (feof(ft->fp))
						return done;
					/* scale signed up to long's range */
					*buf++ = LEFT(datum, 16);
					done++;
				}
				return done;
			case UNSIGNED:
				while(done < nsamp) {
					datum = rshort(ft);
					if (feof(ft->fp))
						return done;
					/* Convert to signed */
					datum ^= 0x8000;
					/* scale signed up to long's range */
					*buf++ = LEFT(datum, 16);
					done++;
				}
				return done;
			case ULAW:
//				fail("No U-Law support for shorts");
				return done;
			case ALAW:
//				fail("No A-Law support for shorts");
				return done;
			}
//		case FLOAT:
//			while(done < nsamp) {
//				datum = dovolume? volume * rfloat(ft)
//						: rfloat(ft);
//				if (feof(ft->fp))
//					return done;
//				*buf++ = LEFT(datum, 16);
//				done++;
//			}
//			return done;
		default:
			return 0;
//			fail("Drop through in rawread!");

		}
//	fail("Sorry, don't have code to read %s, %s",
//		styles[ft->info.style], sizes[ft->info.size]);
	return done;
}

rawstopread(ft_t ft)
{
}

char *extract_name(char *path)
{
	int32 c=strlen(path);
	int32 pos=0;
	
	for(int32 i=0;i<c;i++)
		if(path[i]=='/') pos=i+1;
	
	return &path[pos];
};

int autostartread(ft_t ft)
{
	char *type;
	char header[132];
	if (!ft->seekable)
		return 0;
//		fail("Type AUTO input must be a file, not a pipe");
	if (fread(header, 1, sizeof header, ft->fp) != sizeof header)
		return 0;
//		fail("Type AUTO detects short file");
	fseek(ft->fp, 0L - sizeof header, 1); /* Seek back */
	type = 0;

	{
		char mimetype[512];
		BNode node = BNode(ft->filename);
		BNodeInfo *nodeinfo = new BNodeInfo(&node);
		nodeinfo->GetType(mimetype);
		int len=strlen(mimetype)-1;
		for(;mimetype[len]!='/' && len>=0;len--){};
		type=&mimetype[len+1];
		delete nodeinfo;
	}

	if(	strcmp("au",type)!=0 &&
		strcmp("aiff",type)!=0 &&
		strcmp("hcom",type)!=0 &&
		strcmp("8svx",type)!=0 &&
		strcmp("wav",type)!=0 &&
		strcmp("voc",type)!=0 &&
		strcmp("wve",type)!=0 &&
		strcmp("sf",type)!=0 &&
		strcmp("sndt",type)!=0 &&
		strcmp("infocom",type)!=0 &&
		strcmp("cdr",type)!=0 &&
		strcmp("maud",type)!=0 &&
		strcmp("dat",type)!=0 &&
		strcmp("smp",type)!=0
	)
	{
		char *fname=extract_name(ft->filename);
		int len=strlen(fname)-1;
		for(;fname[len]!='.' && len>=0;len--){};
		type=&fname[len+1];
	
		if(	strcmp("au",type)!=0 &&
			strcmp("aiff",type)!=0 &&
			strcmp("hcom",type)!=0 &&
			strcmp("8svx",type)!=0 &&
			strcmp("wav",type)!=0 &&
			strcmp("voc",type)!=0 &&
			strcmp("wve",type)!=0 &&
			strcmp("sf",type)!=0 &&
			strcmp("sndt",type)!=0 &&
			strcmp("infocom",type)!=0 &&
			strcmp("cdr",type)!=0 &&
			strcmp("maud",type)!=0 &&
			strcmp("dat",type)!=0 &&
			strcmp("smp",type)!=0
		)
		{
			type=0;
			if (strncmp(header, ".snd", 4) == 0 ||
			    strncmp(header, "dns.", 4) == 0 ||
			    header[0] == '\0' && strncmp(header+1, "ds.", 3) == 0) {
				type = "au";
			}
			else if (strncmp(header, "FORM", 4) == 0) {
				if (strncmp(header + 8, "AIFF", 4) == 0)
					type = "aiff";
				else if (strncmp(header + 8, "8SVX", 4) == 0)
					type = "8svx";
				else if (strncmp(header + 8, "MAUD", 4) == 0)
					type = "maud";
			}
			else if (strncmp(header, "RIFF", 4) == 0 &&
				 strncmp(header + 8, "WAVE", 4) == 0) {
				type = "wav";
			}
			else if (strncmp(header, "Creative Voice File", 19) == 0) {
				type = "voc";
			}
			else if (strncmp(header+65, "FSSD", 4) == 0 &&
				 strncmp(header+128, "HCOM", 4) == 0) {
				type = "hcom";
			}
			else if (strncmp(header, "SOUND", 5) == 0) {
				type = "sndt";
			}
		}
	}
  	if (type == 0) {
  		return 0;
	}

	ft->filetype = type;
	static format_t h;
	
	if(strcmp("au",ft->filetype)==0)
	{
		extern austartread(ft_t ft);
		extern auread(ft_t ft, long *buf, int len);
		extern austopread(ft_t ft);

		h.startread=austartread;
		h.read=auread;
		h.stopread=austopread;
	}
	else if(strcmp("aiff",ft->filetype)==0)
	{
		extern aiffstartread(ft_t ft);
		extern aiffread(ft_t ft, long *buf, int len);
		extern aiffstopread(ft_t ft);

		h.startread=aiffstartread;
		h.read=aiffread;
		h.stopread=aiffstopread;
	}
	else if(strcmp("hcom",ft->filetype)==0)
	{
		extern hcomstartread(ft_t ft);
		extern hcomread(ft_t ft, long *buf, int len);
		extern hcomstopread(ft_t ft);

		h.startread=hcomstartread;
		h.read=hcomread;
		h.stopread=hcomstopread;
	}
	else if(strcmp("8svx",ft->filetype)==0)
	{
		extern svxstartread(ft_t ft);
		extern svxread(ft_t ft, long *buf, int len);
		extern svxstopread(ft_t ft);

		h.startread=svxstartread;
		h.read=svxread;
		h.stopread=svxstopread;
	}
	else if(strcmp("wav",ft->filetype)==0)
	{
		extern wavstartread(ft_t ft);
		extern wavread(ft_t ft, long *buf, int len);
		extern wavstopread(ft_t ft);

		h.startread=wavstartread;
		h.read=wavread;
		h.stopread=wavstopread;
	}
	else if(strcmp("voc",ft->filetype)==0)
	{
		extern vocstartread(ft_t ft);
		extern vocread(ft_t ft, long *buf, int len);
		extern vocstopread(ft_t ft);

		h.startread=vocstartread;
		h.read=vocread;
		h.stopread=vocstopread;

	}
	else if(strcmp("wve",ft->filetype)==0)
	{
		extern wvestartread(ft_t ft);
		extern wveread(ft_t ft, long *buf, int len);
		extern wvestopread(ft_t ft);

		h.startread=wvestartread;
		h.read=wveread;
		h.stopread=wvestopread;
	}
	else if(strcmp("sf",ft->filetype)==0)
	{
		extern sfstartread(ft_t ft);

		h.startread=sfstartread;
		h.read=rawread;
		h.stopread=rawstopread;
	}
	else if(strcmp("sndt",ft->filetype)==0)
	{
		extern sndtstartread(ft_t ft);

		h.startread=sndtstartread;
		h.read=rawread;
		h.stopread=rawstopread;
	}
	else if(strcmp("infocom",ft->filetype)==0)
	{
		extern Infocomstartread(ft_t ft);
		extern Infocomread(ft_t ft, long *buf, int len);
		extern Infocomstopread(ft_t ft);

		h.startread=Infocomstartread;
		h.read=Infocomread;
		h.stopread=Infocomstopread;
	}
	else if(strcmp("cdr",ft->filetype)==0)
	{
		extern cdrstartread(ft_t ft);
		extern cdrread(ft_t ft, long *buf, int len);
		extern cdrstopread(ft_t ft);

		h.startread=cdrstartread;
		h.read=cdrread;
		h.stopread=cdrstopread;
	}
	else if(strcmp("dat",ft->filetype)==0)
	{
		extern datstartread(ft_t ft);
		extern datread(ft_t ft, long *buf, int len);
		extern datstopread(ft_t ft);

		h.startread=datstartread;
		h.read=datread;
		h.stopread=datstopread;
	}
	else if(strcmp("smp",ft->filetype)==0)
	{
		extern smpstartread(ft_t ft);
		extern smpread(ft_t ft, long *buf, int len);
		extern smpstopread(ft_t ft);

		h.startread=smpstartread;
		h.read=smpread;
		h.stopread=smpstopread;
	}
	else if(strcmp("maud",ft->filetype)==0)
	{
		extern maudstartread(ft_t ft);
		extern maudread(ft_t ft, long *buf, int len);
		extern maudstopread(ft_t ft);

		h.startread=maudstartread;
		h.read=maudread;
		h.stopread=maudstopread;
	}
	else
	{
		return 0;
	}
	
	ft->h=&h;

	{
		char tmp[512];
		strcpy(tmp,"audio/");
		strcat(tmp,ft->filetype);
		BNode *node = new BNode(ft->filename);
		BNodeInfo *nodeinfo = new BNodeInfo(node);
		nodeinfo->SetType(tmp);
		delete nodeinfo;
		delete node;
	}

	return (* ft->h->startread)(ft);
}

class PrefsView;

struct instance_struct
{
	PrefsView	*prefs_view;
	BMessage 	*prefs;
	long		*buf;
	ft_t 		ft;
	char		afile[256];
	char		atype[256];
	char		amode[256];
	struct soundstream informat;
	int32		volume;
	int32		loop;
	char 		pathsave[1024];
	
	uint32		mover;
	uint32		adder;
};

class PrefsView : public BView
{
	instance_struct	*inst;

	public:
				PrefsView(instance_struct *i):BView(BRect(0,0,199,179),"PrefsView",NULL,B_WILL_DRAW)
				{
					inst=i;
				};
		
	void		Draw(BRect frame)
				{
					SetLowColor(ViewColor());
					const char *orginalcode="Sound Tools © by Lance Norskog";
					const char *dualcode="DualPlayer port by Tinic Uro.";
					SetFont(be_plain_font);
					SetFontSize(10);
					SetDrawingMode(B_OP_COPY);
					DrawString(orginalcode,BPoint((200-StringWidth(orginalcode))/2,164));
					DrawString(dualcode,BPoint((200-StringWidth(dualcode))/2,176));
					BView::Draw(frame);
				}
};

long class_dispatcher(Class *c, Object *o, ulong MethodID, ulong *data)
{
	instance_struct *inst=(instance_struct *)o->Instance(c);	

	o->SetError(B_NO_ERROR);	

	switch(MethodID)
	{

		case	B_METHOD_CONSTRUCT:	// void (void)
				{					
					inst->prefs_view 	= new PrefsView(inst);
					inst->prefs 		= NULL;
					inst->ft			= &inst->informat;

					BMimeType *mime = new BMimeType("audio/smp");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","smp");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("SMP file");
						mime->SetLongDescription("Turtle Beach SampleVision File.");
						mime->Install();
						delete msg;
					}
					delete mime;

					mime = new BMimeType("audio/dat");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","dat");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("DAT file");
						mime->SetLongDescription("Text Data Sound File.");
						mime->Install();
						delete msg;
					}
					delete mime;
					
					mime = new BMimeType("audio/maud");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","maud");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("MAUD file");
						mime->SetLongDescription("MacroSystem Sound File.");
						mime->Install();
						delete msg;
					}
					delete mime;
					
					mime = new BMimeType("audio/cdr");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","cdr");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("CD-R file");
						mime->SetLongDescription("CD-R Sound File.");
						mime->Install();
						delete msg;
					}
					delete mime;
					
					mime = new BMimeType("audio/infocom");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","infocom");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("Infocom file");
						mime->SetLongDescription("Infocom Sound File.");
						mime->Install();
						delete msg;
					}
					delete mime;
					
					mime = new BMimeType("audio/sf");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","sf");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("SF file");
						mime->SetLongDescription("IRCAM Sound File.");
						mime->Install();
						delete msg;
					}
					delete mime;
					
					mime = new BMimeType("audio/wve");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","wve");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("WVE file");
						mime->SetLongDescription("Psion 8-bit Alaw File.");
						mime->Install();
						delete msg;
					}
					delete mime;
					
					mime = new BMimeType("audio/voc");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","voc");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("VOC file");
						mime->SetLongDescription("Sound Blaster VOC file.");
						mime->Install();
						delete msg;
					}
					delete mime;
					
					mime = new BMimeType("audio/wav");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","wav");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("WAV file");
						mime->SetLongDescription("Windows 3.0 .WAV RIFF File.");
						mime->Install();
						delete msg;
					}
					delete mime;
					
					mime = new BMimeType("audio/8svx");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","8svx");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("8SVX file");
						mime->SetLongDescription("8SVX Musical Instrument.");
						mime->Install();
						delete msg;
					}
					delete mime;
					
					mime = new BMimeType("audio/hcom");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","hcom");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("HCOM file");
						mime->SetLongDescription("Macintosh HCOM File.");
						mime->Install();
						delete msg;
					}
					delete mime;
					
					mime = new BMimeType("audio/aiff");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","aiff");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("AIFF file");
						mime->SetLongDescription("AIFF files used on Apple IIc/IIgs and SGI.");
						mime->Install();
						delete msg;
					}
					delete mime;

					mime = new BMimeType("audio/au");
					if(!mime->IsInstalled())
					{
						BMessage *msg = new BMessage();
						msg->AddString("extensions","au");
						mime->SetFileExtensions((const BMessage *)msg);
						mime->SetPreferredApp("application/x-tinic.DualPlayer");
						mime->SetShortDescription("Sun Audio file");
						mime->SetLongDescription("SUN Microsystems AU File.");
						mime->Install();
						delete msg;
					}
					delete mime;
					
					return 0;
				}

		case	B_METHOD_DESTROY:	// void (void)
				{
					return 0;
				}				
				
		case	P_LOAD:				// bool handle (char *path)
				{			
					char *path=(char *)data[0];
					
					strcpy(inst->pathsave,path);					
										
					inst->buf = 0;
					if(inst->ft->fp=fopen(path,"r"))
					{				 	
						inst->ft->filename 		= strdup(path);
						inst->ft->seekable		= 1;
						inst->ft->info.rate		= 0;
						inst->ft->info.size		= -1;
						inst->ft->info.style	= -1;
						inst->ft->info.channels	= -1;
						inst->ft->swap			= 0;
						inst->ft->filetype		= (char *)0;
						inst->ft->comment		= (char *)0;

						sprintf(inst->afile,extract_name(path));

						if(autostartread(inst->ft)) 
						{
							// We dont support higher rates yet...
							if(inst->ft->info.rate<65536) return true;
						}
					}
					
					return false;
				}
									
		case	P_FREE:				// void (int handle)
				{
					int handle=(int)data[0];

					inst->ft->h->stopread(inst->ft);

					if(inst->ft->fp)fclose(inst->ft->fp);
					inst->ft->fp=0;
					if(inst->buf) free(inst->buf);
					inst->buf=0;
				
					return 0;
				}

		case	P_RESUME:			// void (int handle)
				{
					int handle=(int)data[0];
					return 0;
				}

		case	P_PAUSE:			// void (int handle)
				{
					int handle=(int)data[0];
					return 0;
				}
					
		case	P_SETUPSTREAM:		// void (BAudioSubscriber *auds)
				{
					return 0;
				}
				
		case	P_STREAM:			// bool (void *arg, char *buffer, int size)
				{
					void *arg		=(void *)data[0];
					int16 *buffer	=(int16 *)data[1];
					int size		=(int)data[2]/sizeof(int16);
					int rsize;

					switch(inst->ft->info.channels)
					{
						case	1:
								rsize=size/2;
								break;
						case	2:
								rsize=size;
								break;
// not supported yet
//						case	4:
//								rsize=size*2;
//								break;
					}
					
					uint32 inputsamples = (inst->adder*rsize)/16384;
					
					if(inst->buf==0)
					{
						inst->mover = 0;
						inst->adder = ((uint32)inst->ft->info.rate*(uint32)16384)/44100;
						     if(strcmp("au",inst->ft->filetype)==0) 		strcpy(inst->atype,"SUN Microsystems AU File");
						else if(strcmp("aiff",inst->ft->filetype)==0) 		strcpy(inst->atype,"AIFF files used on Apple IIc/IIgs and SGI");
						else if(strcmp("hcom",inst->ft->filetype)==0) 		strcpy(inst->atype,"Macintosh HCOM File");
						else if(strcmp("8svx",inst->ft->filetype)==0) 		strcpy(inst->atype,"8SVX Musical Instrument");
						else if(strcmp("wav",inst->ft->filetype)==0)		strcpy(inst->atype,"Windows 3.0 .WAV RIFF File");
						else if(strcmp("voc",inst->ft->filetype)==0) 		strcpy(inst->atype,"Sound Blaster VOC file");
						else if(strcmp("wve",inst->ft->filetype)==0) 		strcpy(inst->atype,"Psion 8-bit Alaw File");
						else if(strcmp("sf",inst->ft->filetype)==0) 		strcpy(inst->atype,"IRCAM Sound File");
						else if(strcmp("sndt",inst->ft->filetype)==0) 		strcpy(inst->atype,"SNDT file");
						else if(strcmp("infocom",inst->ft->filetype)==0) 	strcpy(inst->atype,"Infocom Sound File");
						else if(strcmp("cdr",inst->ft->filetype)==0) 		strcpy(inst->atype,"CD-R Sound File");
						else if(strcmp("maud",inst->ft->filetype)==0) 		strcpy(inst->atype,"MacroSystem Sound File");
						else if(strcmp("dat",inst->ft->filetype)==0) 		strcpy(inst->atype,"Text Data Sound File");
						else if(strcmp("smp",inst->ft->filetype)==0)		strcpy(inst->atype,"Turtle Beach SampleVision File");
						sprintf(inst->amode,"%d Hz, %d channel(s)",inst->ft->info.rate,inst->ft->info.channels);

						inputsamples = (inst->adder*rsize)/16384;
						
						inst->buf = (long *)malloc((inputsamples+8)*sizeof(long));
					}					
					
					inst->mover&=0x3FFF;

					if(inst->ft->h->read(inst->ft, inst->buf, inputsamples))
					{
						switch(inst->ft->info.channels)
						{
							case	1:
									for(int i=0;i<(size/2);i++)
									{
										int16 val=((inst->buf[inst->mover/16384]/128)*inst->volume)/65536;
										buffer[i*2+0]=val;
										buffer[i*2+1]=val;
										inst->mover+=inst->adder;
									}
									break;
							case	2:
									for(int i=0;i<size;i++)
									{
										buffer[i]=((inst->buf[inst->mover/16384]/128)*inst->volume)/65536;
										inst->mover+=inst->adder;
									}
									break;
// not supported yet
//							case	4:
//									for(int i=0;i<size;i+=2)
//									{
//										buffer[i+0]=(((inst->buf[((i+0)*2)+0]/128)*inst->volume)+inst->buf[((i+0)*2)+1])/2/65536;
//										buffer[i+1]=(((inst->buf[((i+1)*2)+0]/128)*inst->volume)+inst->buf[((i+1)*2)+1])/2/65536;
//									}
//									break;
						}
						return 1;
					}
					else
					{
						if(inst->loop)
						{
							// Hmm... no the best way, to do this...
							o->DoMethod(P_FREE);
							if(o->DoMethod(P_LOAD,inst->pathsave))
								return 1;
							else
								return 0;
						}
						else
						{
							return 0;
						}
					}
				}
								
		case	P_SETATTR:			//  void (ulong AttributeID, ulong data)
				{
					ulong ATTR =(ulong)data[0];
					ulong DATA =(ulong)data[1];

					switch(ATTR)
					{
						case	P_ATTR_PREFS:				// Setup the pointer to the preferences BMessage
								inst->prefs=(BMessage *)DATA;
								if(!inst->prefs->HasBool("SampleFiletypeCheck"))inst->prefs->AddBool("SampleFiletypeCheck",TRUE);
								break;
						case	P_ATTR_BOOST:				// Set volume 0..128, special boost from 128..255
								inst->volume=(int)DATA;
								break;
						case	P_ATTR_LOOP:				
								inst->loop=(bool)DATA;
								break;
					}
					o->DoSuperMethod(c,P_SETATTR,data);
					return 0;
				}
				
		case	P_GETATTR:			//  void (ulong AttributeID, ulong data)
				{
					ulong ATTR =(ulong)data[0];
					ulong DATA =(ulong)data[1];

					switch(ATTR)
					{
						case	P_ATTR_STREAMARG:			// Argument which should be forwarded to the stream function or 0
								*((int *)DATA)=0;
								break;
						case	P_ATTR_ID:					// ID String which is displayed in the ListView, this must be valid!
								*((char **)DATA)=PLAYER_NAME;
								break;
						case	P_ATTR_VIEW:				// Get the pointer to the Preferences BView, this must be valid!
								*((BView **)DATA)=inst->prefs_view;
								break;
						case	P_ATTR_RECOGNITION:
								*((int *)DATA)=80;
								break;
						default:
								return o->DoSuperMethod(c,P_GETATTR,data);
					}
					
					return 0;
				}
				
		case	P_DRAWSTATUS:		// void (BView *view)
				{
					char str[256];
					BView *view=(BView *)data[0];
					
					view->MovePenTo(BPoint(4, 11));
					view->DrawString("File");
					view->MovePenTo(BPoint(40, 11));
					sprintf(str,": %s",inst->afile);
					view->DrawString(str);
					view->MovePenTo(BPoint(4, 22));
					view->DrawString("Type");
				 	view->MovePenTo(BPoint(40, 22));
				 	sprintf(str,": %s",inst->atype);
					view->DrawString(str);
					view->MovePenTo(BPoint(4, 33));
					view->DrawString("Mode");
					view->MovePenTo(BPoint(40, 33));
					sprintf(str,": %s",inst->amode);
					view->DrawString(str);

					return 0;
				}
				
		case	P_CREATEINFO: 		// void (char ***info)
				{
					char ***info=(char ***)data[0];
					*info=0;	// Safety settings
					return 0;
				}

		case	P_FREEINFO: 		// void (char ***info, int *lines)
				{
					char ***info=(char ***)data[0];
					return 0;
				}

		default:
				return o->DoSuperMethod(c,MethodID,data);
	}
}

char *class_superclass()	// Superclassname for ALL players
{
	return "dualplayer/player/baseplayer.zclass";
};

long class_instancesize()
{
	return sizeof(struct instance_struct);
};

long class_superversion()	// minimum version needed of the superclass
{
	return 2;
};

long class_version()		// This class version
{
	return 2;
};
