/*

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"
#ifdef NCURSES
  #include <ncurses.h>
#endif

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"
"  -m      Force mono output (so sb-pro can mix at 44100)\n"
"  -8      Force 8 bit output\n"
"  -i      Use interpolated mixing\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);
}


int main(int nargc,char *nargv[])
{
	UNIMOD *mf;
	int cmderr=0;                   /* error in commandline flag */
	int morehelp=0;                 /* set if user wants more help */
	int quit;
	int t;

#ifdef NCURSES
	/* initialize curses code */
        atexit((void*)endwin);
        initscr();
        cbreak();
        nodelay(stdscr, TRUE);
        noecho();
#endif                                                

	puts(mikbanner);

	/*
		Initialize soundcard parameters.. you _have_ to do this
		before calling MD_Init(), and it's illegal to change them
		after you've called MD_Init()
	*/

	md_mixfreq      =44100;                     /* standard mixing freq */
	md_dmabufsize   =10000;                     /* standard dma buf size */
	md_mode         =DMODE_16BITS|DMODE_STEREO; /* standard mixing mode */
	md_device       =0;                                                     /* standard device: autodetect */

	/*
		Register the loaders we want to use..
	*/

	ML_RegisterLoader(&load_m15);    /* if you use m15load, register it as first! */
	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);

	/*
		Register the drivers we want to use:
	*/

	MD_RegisterDriver(&drv_nos);

#ifdef __alpha
	MD_RegisterDriver(&drv_af);
#elif defined(__sun__)
	MD_RegisterDriver(&drv_sun);
#else
	MD_RegisterDriver(&drv_vox);
#endif

	MD_RegisterPlayer(tickhandler);

	/* Parse option switches using standard getopt function: */

	opterr=0;

	while( !cmderr &&
		  (t=getopt(nargc,nargv,"ohxpm8irv: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 '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){

		/*
			there was an error in the commandline, or there were no true
			arguments, so display a usage message
		*/

		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);
	}

	/*  initialize soundcard */

	if(!MD_Init()){
		printf("Driver error: %s.\n",myerr);
		return 0;
	}

	printf("Using %s for %d bit %s %s sound at %u Hz\n\n",
			md_driver->Name,
			(md_mode&DMODE_16BITS) ? 16:8,
			(md_mode&DMODE_INTERP) ? "interpolated":"normal",
			(md_mode&DMODE_STEREO) ? "stereo":"mono",
			md_mixfreq);

	for(quit=0; !quit && optind<nargc; optind++){

		printf("File    : %s\n",nargv[optind]);

		/* load the module */

		mf=ML_LoadFN(nargv[optind]);

		/* didn't work -> exit with errormsg. */

		if(mf==NULL){
			printf("MikMod Error: %s\n",myerr);
			break;
		}

		/*      initialize modplayer to play this module */

		MP_Init(mf);

		printf( "Songname: %s\n"
				"Modtype : %s\n"
				"Periods : %s,%s\n",
				mf->songname,
				mf->modtype,
				(mf->flags&UF_XMPERIODS) ? "XM type" : "mod type",
				(mf->flags&UF_LINEAR) ? "Linear" : "Log");

                fflush(stdout); /* Make sure that screen buffering isn't used */
                    
		/*
			set the number of voices to use.. you
			could add extra channels here (e.g. md_numchn=mf->numchn+4; )
			to use for your own soundeffects:
		*/

		md_numchn=mf->numchn;

		/*  start playing the module: */

		MD_PlayStart();

		while(!MP_Ready()){
#ifdef NCURSES
                        char c;
                        
                        if ((c=getch()) == ERR) c = 0;
						if(c=='+')
                            MP_NextPosition();
                        else if(c=='-')
                            MP_PrevPosition();
                        else if(c==0x1b){
                            quit=1;
                            break;
                            }
                        else if(c==' ') break;
#endif
			MD_Update();
			
			/* no need to wait with linux voxware */

			printf("\rsngpos:%d patpos:%d sngspd %d bpm %d   ",mp_sngpos,mp_patpos,mp_sngspd,mp_bpm);
			fflush(stdout);
		}

		MD_PlayStop();          /* stop playing */
		ML_Free(mf);            /* and free the module */

		puts("\n");
	}

	MD_Exit();
	return 0;
}
