/*
 * File: mp_main.c
 * SGoldthorpe	20-Jul-91
 */

/*
 * mp_main - main bit of midiplay
 * This software is (C) 1991 Stephen Goldthorpe but it's FREE!  Usual
 * disclaimers and notices about this software not being sold for profit.
 * But you may take all you want from the code though!  If you have any
 * suggestions/bug fixes please get in contact with me.  I don't want to
 * maintain code i've never even seen before (life's hard enough without all
 * of that)!
 *						-Steve Goldthorpe
 * Phone (DAYTIME UK):	+44 707 382350
 * Internet E-Mail:	SGoldthorpe.wgc-e@rx.xerox.com
 *			goldthor@arisia.xerox.com
 *
 * Version 0.5 by Piet van Oostrum <piet@cs.ruu.nl>
 * November 1991.
 * Added -T option
 * Support for files > 32KB
 * See also mp_intp.c
 */

#include	<stdio.h>
#include	<types.h>
#include	<stat.h>
#include	<fcntl.h>
#include	<malloc.h>
#include	<errno.h>

/* #include	"midiplay.h" included in mp_gbls.h */
#include	"mp_gbls.h"

/* EXTERNAL DECLS */
extern int	interp();
extern long lread();
extern char * lalloc();

/* GLOBAL VARIABLES */
BYTE	*file_buff;
long	buf_size;

/* FUNCTION DECLS */
static BOOL	play();
static void	parse_flags(), do_help();

/* MAIN CODE - SHORT & SWEET */
int	main(argc,argv)
int	argc;
char	*argv[];
{   int	arg_n;

    /* title (so you and I know what's what) */
    printf("%s v %d.%d (%s)\n",app_name,RELEASE,VERSION,DATE);

    /* check args */
    if(argc<2)
    {	fprintf(stderr,"%s: -h | {-CPSTcilmnpt} <file1> {...<fileN>}\n",
	    app_name);
	exit();
    };

    /* get flags from arg list */
    for(arg_n=1;arg_n<argc;arg_n++)
	if(*argv[arg_n]=='-')
	    parse_flags(argv[arg_n]);

    /* now get some workspace... */
#ifdef DEBUG
    fprintf(stderr,"%s: malloc (%d)\n",app_name,BUFFER_SIZE);
#endif
    if((file_buff=(BYTE*)malloc(BUFFER_SIZE))==NULL)
    {	fprintf(stderr,"%s: couldn't get enough memory for buffer\n",app_name);
	exit();
    };
    buf_size = BUFFER_SIZE;

    /* play all files in arg list */
    for(arg_n=1;arg_n<argc;arg_n++)
	if(*argv[arg_n]!='-')
	    if(play(argv[arg_n]))
		break;

    /* and tidy up */
    free((char*)file_buff);
};

/* FUNCTION DEFS */
static void	parse_flags(flags)
char	*flags;
{   int	c;
    for(c=1;c<strlen(flags);c++)
	switch(*(flags+c))
	{   case 'h':
		do_help();
		exit();
	    case 't':
		f_text=TRUE;
		break;
	    case 'c':
		f_copyright=TRUE;
		break;
	    case 'n':
		f_track_name=TRUE;
		break;
	    case 'i':
		f_instrument=TRUE;
		break;
	    case 'l':
		f_lyric=TRUE;
		break;
	    case 'm':
		f_marker=TRUE;
		break;
	    case 'p':
		f_prompt=TRUE;
		break;
	    case 'P':
		f_Program=TRUE;
		break;
	    case 'C':
		f_Channel_pressure=TRUE;
		break;
	    case 'S':
		f_Sysex = TRUE;
		break;
	    case 'T':
		f_Timing = TRUE;
		break;
	    default:
		fprintf(stderr,"bad flag '%c'\n",*(flags+c));
		break;
	    };
};

static void	do_help()
{	printf("help\n");
	printf("	%s plays midi files format 0 and 1.\n",app_name);
	printf("syntax:\n");
	printf("	%s -h | {-CPScilmnpt} <file1> {...<fileN>}\n",app_name);
	printf("where\n");
	printf("	h = This help message,\n");
	printf("	C = Send channel pressure data,\n");
	printf("	P = Send program data,\n");
	printf("	S = Send system exclusive data,\n");
	printf("	T = Send timing data,\n");
	printf("	c = Print copyright messages,\n");
	printf("	i = Print instrument assignments,\n");
	printf("	m = Print song markers,\n");
	printf("	n = Print sequence, track names,\n");
	printf("	p = Print cueing prompts,\n");
	printf("	t = Print general text information.\n\n");
	printf("%s can be stopped by CTRL C and tracks skipped with CTRL S.\
\n",app_name);
};

static BOOL	play(file)
char	*file;
{   struct stat	stat_buff;
    long	len;
    int		fd;
#ifdef DEBUG
    fprintf(stderr,"%s: play %s\n",app_name,file);
#endif

    /* open the file (is possible)  and get info */
    if((fd=open(file,O_RDONLY))<0)
    {	fprintf(stderr,"%s: can't open %s\n",app_name,file);
	return(FALSE);
    };
    if(stat(file,&stat_buff)<0)
    {	perror(app_name);
	return(FALSE);
    };
    if(stat_buff.st_size>BUFFER_SIZE)
    {	fprintf(stderr,"%s: %s too long for buffer\n",app_name,file);
	close(fd);
	return(FALSE);
    };
    len=stat_buff.st_size;
    if (len > buf_size) {
    	free (file_buff);
	file_buff = lalloc(len);
	buf_size = len;
    }

    /* ...and fill the buffer */
    if(lread(fd,(BYTE*)file_buff,len)!=len)
    {	fprintf(stderr,"%s: problem reading %s\n",app_name,file);
	close(fd);
	free((char*)file_buff);
	return(FALSE);
    };
    close(fd);

    /* send it to interp for the hard work */
    return(interp(file_buff,file,len));
};

/*
 * REVISION LOG
 * ============
 * 0.1	SGoldthorpe	20-Mar-91	Created for Atari ST / Sozobon C.  It's
 *					a bit atari specific in places but i've
 *					tried to make it UNIX(tm) looking for
 *					easier porting (if anyone feels brave
 *					enough to try.
 * 0.2	SGoldthorpe	 7-Apr-91	Messed up the code in mp_intp to
 *					allow type 1 midi files.  Timing is
 *					still a bit hairy but it plays 80%
 *					of the files I have OK.
 * 0.3	SGoldthorpe	27-May-91	Reformatted & tidied up, sorted out
 *					running status and added flags.
 * 0.4	SGoldthorpe	20-Jul-91	Generally restructed, tidied up and
 *					added sysex capabilities.
 *
 */
