/*

Name:
MIKMOD.C

Description:
Modplaying example of mikmod - bare linux (unix?) version.

2.10 - ncurses support added by Rao. simply define NCURSES to enable it

*/

/*

*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "mikmod.h"

#ifndef _APPLICATION_H
#include <Application.h>
#include <Store.h>
#endif

#include <getopt.h>

char helptext[]=

"Available switches (CaSe SeNsItIvE!):\n"
"\n"
"  -d x    use device-driver #x for output (0 is autodetect). Default=0\n"
"  -ld     List all available device-drivers\n"
"  -ll     List all available loaders\n"
"  -x      disables protracker extended speed\n"
"  -p      disables panning effects (9fingers.mod)\n"
"  -v xx   Sets volume from 0 (silence) to 100. Default=100\n"
"  -f xxxx Sets mixing frequency. Default=44100\n"
"          Allowed:  5510,  6620,  8000, 9600,  11025, 16000,\n" 
"                   18900, 22050, 27420, 32000, 33075, 37800,\n" 
"                   44100, 48000\n"
"  -m      Force mono output (so sb-pro can mix at 44100)\n"
"  -8      Force 8 bit output\n"
"  -i      Use interpolated mixing\n"
"  -s      Sourround: Disable Headphone playing\n"
"  -r      Restart a module when it's done playing";


void tickhandler(void)
{
	MP_HandleTick();    /* play 1 tick of the module */
	MD_SetBPM(mp_bpm);
}

UNIMOD *mf=NULL;

MikMod 		*my_app; 
MikWindow	*aWindow;
MikView		*aView;

MikView::MikView(BRect rect, char *name):BView(rect, name, B_FOLLOW_ALL, B_WILL_DRAW)
{
}

void MikView::AttachedToWindow()
{
	SetFontName("Kate");
	SetFontSize(10);
}

void MikView::Draw(BRect /* updateRect */)
{
	char str[256];
	if(mf)
	{
		MovePenTo(BPoint(4, 10));
		sprintf(str,"Songname: %s",mf->songname);
		DrawString(str);
		MovePenTo(BPoint(4, 20));
		sprintf(str,"Modtype : %s",mf->modtype);
		DrawString(str);
		MovePenTo(BPoint(4, 30));
		sprintf(str,"Playmode: %d voices, %d rate",mf->numchn,md_mixfreq);
		DrawString(str);
	}
	else
	{
		MovePenTo(BPoint(12,20));
		DrawString("Drag MOD, XM or S3M files on me!");
	}
}

void MikView::DrawSongPos(void)
{
	char str[256];
	if(mf)
	{
		SetHighColor(255,255,255);
		FillRect(BRect(165,20,270,53));
		SetHighColor(0,0,0);
		MovePenTo(BPoint(165,30));
		sprintf(str,"POS %03d %03d",mp_sngpos,mp_patpos);
		DrawString(str);	
	}
}

bool MikView::MessageDropped(BMessage *msg,BPoint loc,BPoint offset)
{
	record_ref theRef;
	BFile *theFile;
	long counter;
	long countFound;
	ulong typeFound;
	  
	if (!msg->GetInfo("refs", &typeFound, &countFound))return(FALSE);
	if (countFound < 1) return(FALSE);

	for (counter = 0; counter < countFound; counter++) 
	{
		theRef = msg->FindRef("refs", counter);
		
        if (does_ref_conform(theRef, "File")) 
        {
			char   *name;
			if(mf)aWindow->FreeMOD();
			theFile = new BFile(theRef);
			name=(char *)malloc(1024);
			theFile->GetPath(name,1024);
			aWindow->LoadMOD(name);
			if(mf)
			{
				char str[255];
				SetHighColor(255,255,255);
				FillRect(BRect(0,0,270,53));
				SetHighColor(0,0,0);
				MovePenTo(BPoint(4, 10));
				sprintf(str,"Songname: %s\n",mf->songname);
				DrawString(str);
				MovePenTo(BPoint(4, 20));
				sprintf(str,"Modtype : %s\n",mf->modtype);
				DrawString(str);
				MovePenTo(BPoint(4, 30));
				sprintf(str,"Playmode: %d voices, %d rate",mf->numchn,md_mixfreq);
				DrawString(str);
			}
			free(name);
    	}
	}	
	return (TRUE);
}

MikWindow::MikWindow(BRect frame, char *filename):BWindow(frame,"MikMod 2.10 for BeOS by Tinic Urou",B_TITLED_WINDOW,B_NOT_ZOOMABLE|B_NOT_RESIZABLE)
{
	if(filename) LoadMOD(filename);
}

void MikWindow::LoadMOD(char *filename)
{
	if(mf=ML_LoadFN(filename))
	{
		MP_Init(mf);
		md_numchn=mf->numchn;
		MD_PlayStart();
		MD_Update(); 
	}
}

void MikWindow::FreeMOD(void)
{
	MD_PlayStop(); 
	ML_Free(mf);  
	mf=NULL;
}

bool MikWindow::QuitRequested()
{
	if(mf) FreeMOD();
	my_app->PostMessage(B_QUIT_REQUESTED);
	return TRUE;
}

MikMod::MikMod(char *filename):BApplication('MIKM')
{
	BRect			aRect;
	
	BPopUpMenu *menu = new BPopUpMenu("", FALSE, FALSE);
	BMenuItem *item;
	item = new BMenuItem("Quit MikMod", new BMessage(B_QUIT_REQUESTED), 'Q');
	menu->AddItem(item);
	menu->SetTargetForItems(my_app);
	SetMainMenu(menu);
	
	aRect.Set(90, 37, 335, 70);
	aWindow = new MikWindow(aRect,filename);
	
	aRect.OffsetTo(B_ORIGIN);
	aView = new MikView(aRect,"MikView");
	
	aWindow->AddChild(aView);
	aWindow->Show();	
}

int main(int nargc,char *nargv[])
{
	int    cmderr=0;                 
	int    morehelp=0;               
	int    quit;
	int    t;  
	char   *filename;                                       

	md_mixfreq      =44100;                   
	md_dmabufsize   =8192;                     
	md_mode         =DMODE_16BITS|DMODE_STEREO|DMODE_HEADPH; 
	md_device       =0;                                                   

	ML_RegisterLoader(&load_m15);   
	ML_RegisterLoader(&load_mod);
	ML_RegisterLoader(&load_mtm);
	ML_RegisterLoader(&load_s3m);
	ML_RegisterLoader(&load_stm);
	ML_RegisterLoader(&load_ult);
	ML_RegisterLoader(&load_uni);
	ML_RegisterLoader(&load_xm);

	

	MD_RegisterDriver(&drv_nos);
	MD_RegisterDriver(&drv_be);
//	MD_RegisterDriver(&drv_raw);
	
	MD_RegisterPlayer(tickhandler);

	opterr=0;

	while( !cmderr && (t=getopt(nargc,nargv,"shxpm8irv:f:l:d:")) != EOF )
	{
		switch(t)
		{

			case 'd':
				md_device=atoi(optarg);
				break;

			case 'l':
				if(optarg[0]=='d') MD_InfoDriver();
				else if(optarg[0]=='l') ML_InfoLoader();
				else{
					cmderr=1;
					break;
				}
				exit(0);

			case 'r':
				mp_loop=1;
				break;

			case 'm':
				md_mode&=~DMODE_STEREO;
				break;

			case '8':
				md_mode&=~DMODE_16BITS;
				break;

			case 'i':
				md_mode|=DMODE_INTERP;
				break;
				
			case 's':
				md_mode&=~DMODE_HEADPH;

			case 'x':
				mp_extspd=0;
				break;

			case 'p':
				mp_panning=0;
				break;

			case 'v':
				if((mp_volume=atoi(optarg))>100) mp_volume=100;
				break;

			case 'f':
				md_mixfreq=atol(optarg);
				break;

			case 'h':
				morehelp=1;
				cmderr=1;
				break;

			case '?':
				puts("\07Invalid switch or option needs an argument\n");
				cmderr=1;
				break;
		}
	}

/*	if(cmderr || optind>=nargc){

		printf("Usage: %s [switches] <fletch.mod> ... \n",nargv[0]);

		if(morehelp)
			puts(helptext);
		else
                        printf("Type %s -h for more help.\n",nargv[0]);

		exit(-1);
	}*/
	
	if(MD_Init())
	{
		filename=nargv[optind];

		if(!filename) mp_loop=1; // Were probaly not in CLI...

		my_app = new MikMod(filename);
		my_app->Run();

		delete(my_app);

		MD_Exit();
	}
	else
	{
		printf("Driver error: %s.\n",myerr);
		return 0;
	}
	return 0;
}
