/* this file is a part of amp software, (C) tomislav uzelac 1996,1997
*/

/* audio.c	main amp source file 
 *
 * Created by: tomislav uzelac	Apr 1996 
 * Karl Anders Oygard added the IRIX code, 10 Mar 1997.
 * Ilkka Karvinen fixed /dev/dsp initialization, 11 Mar 1997.
 * Lutz Vieweg added the HP/UX code, 14 Mar 1997.
 * Dan Nelson added FreeBSD modifications, 23 Mar 1997.
 * Andrew Richards complete reorganisation, new features, 25 Mar 1997
 * Edouard Lafargue added sajber jukebox support, 12 May 1997
 */ 


#include "amp.h"
#include "dump.h"

#include <sys/types.h>
#include <sys/stat.h>

#ifndef __BEOS__
#include <sys/uio.h>
#endif

#include <sys/socket.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define AUDIO
#include "audio.h"
#include "formats.h"
#include "getbits.h"
#include "huffman.h"
#include "layer2.h"
#include "layer3.h"
#include "position.h"
#include "rtbuf.h"
#include "transform.h"
#include "controldata.h"
#include "guicontrol.h"

#ifndef __BEOS__
typedef int bool;
#endif

void statusDisplay(struct AUDIO_HEADER *header, int frameNo)
{
	int minutes,seconds;

	if ((A_SHOW_CNT || A_SHOW_TIME) && !(frameNo%10))
		msg("\r");
	if (A_SHOW_CNT && !(frameNo%10) ) {
		msg("{ %d } ",frameNo);
	}
	if (A_SHOW_TIME && !(frameNo%10)) {
		seconds=frameNo*1152/t_sampling_frequency[header->ID][header->sampling_frequency];
		minutes=seconds/60;
		seconds=seconds % 60;
		msg("[%d:%02d]",minutes,seconds);
	}
	if (A_SHOW_CNT || A_SHOW_TIME)
		fflush(stderr);
}

int decodeMPEG(char *inFileStr, char *outFileStr)
{
struct AUDIO_HEADER header;
int cnt,g,err=0;
int audio_set_up=FALSE;
	
	if (strcmp(inFileStr,"-")==0)
		in_file=stdin;
	else {
		if ((in_file=fopen(inFileStr,"r"))==NULL) {
			warn("Could not open file: %s\n",inFileStr);
			return(1);
		}
	}

	if (outFileStr) {
		if (strcmp(outFileStr,"-")==0)
			out_file=stdout;
	else
		if ((out_file=fopen(outFileStr,"w"))==NULL) {
			warn("Could not write to file: %s\n",outFileStr);
			return(1);
		}
		msg("Converting: %s\n",inFileStr);
	}

	if (A_AUDIO_PLAY)
		msg("Playing: %s\n",inFileStr);

	append=data=nch=0; /* initialize globals */
        f_bdirty=TRUE;
        bclean_bytes=0;


	if (A_FORMAT_WAVE) wav_begin();

/*
 *     *************************************************************************
 */
	for (cnt=0;;cnt++) {
		if ((g=gethdr(&header))!=0) {
			switch (g) {
				case GETHDR_ERR: die("error reading mpeg bitstream. exiting.\n");
							break;
				case GETHDR_NS : warn("this is a file in MPEG 2.5 format, which is not defined\n");
						 warn("by ISO/MPEG. It is \"a special Fraunhofer format\".\n");
						 warn("amp does not support this format. sorry.\n");
							break;
				case GETHDR_FL1: warn("ISO/MPEG layer 1 is not supported by amp (yet).\n");
							break;
				case GETHDR_FF : warn("free format bitstreams are not supported. sorry.\n");
							break;	
				case GETHDR_SYN: warn("oops, we're out of sync.\n");
							break;
				case GETHDR_EOF: if (A_FORMAT_WAVE) wav_end(&header);
							break;
				default: 
							break;
			}
			break;
                }

		/* crc is read just to get out of the way.
		 */
		if (header.protection_bit==0) getcrc();

		statusDisplay(&header,cnt);	

		if (!audio_set_up && A_AUDIO_PLAY) { /* setup the audio when we have the frame info */
			show_header(&header);
			if (AUDIO_BUFFER_SIZE==0)
				audioOpen(t_sampling_frequency[header.ID][header.sampling_frequency],
						(header.mode!=3),A_SET_VOLUME);
			else
				audioBufferOpen(t_sampling_frequency[header.ID][header.sampling_frequency],
						(header.mode!=3),A_SET_VOLUME);
			audio_set_up=TRUE;
		}

		if (header.layer==1) {
			if (layer3_frame(&header,cnt)) {
				warn(" error. blip.\n");
				err=1;
				break;
			}
		} else if (header.layer==2)
			if (layer2_frame(&header,cnt)) {
                                warn(" error. blip.\n");
                                err=1;
                                break;
                        }
 
	}
/*
 *     *************************************************************************
 */
	fclose(in_file);
	if (A_AUDIO_PLAY)
		if (AUDIO_BUFFER_SIZE!=0)
			audioBufferClose();
		else
			audioClose();
	else
		fclose(out_file);

	msg("\n");
	return(err);
}

int main(int argc,char **argv)
{
	int argPos;

	argPos=args(argc,argv); /* process command line arguments */

	/* premultiply dewindowing tables.  Should go away
	*/
		premultiply();

	/* init imdct tables
	*/
		imdct_init();

  if (argc == 1) /* Start amp as a GUI backend. */
    {
/*       AUDIO_BUFFER_SIZE = 0; */
      A_QUIET = TRUE;
      gui_control();
    }
  else
    {

	if (A_AUDIO_PLAY) {			/* play each specified file */
		if (argPos<argc)
			for(;argPos<argc;argPos++) {
#ifdef LINUX_REALTIME
                                if (geteuid() != 0) {
                                        warn("effective UID not root, cannot use realtime buffering\n");
                                        decodeMPEG(argv[argPos],0);
                                } else 
                                        rt_play(argv[argPos]);
#else /* LINUX_REALTIME */
				decodeMPEG(argv[argPos],0);
#endif /* LINUX_REALTIME */
			}
		else
			displayUsage();
	} else {								/* convert the file to some format */
		if ((argPos+2)==argc)
			decodeMPEG(argv[argPos],argv[argPos+1]);
		else {
			warn("Invalid number of parameters\n");
			displayUsage();
			die("");
		}
	}

	msg("\nThank you for using amp!\n");
	exit(0);
    }
  exit(0);
}
