/*************************************************************
 *   mpgtx an mpeg toolbox                                   *
 *   by Laurent Alacoque <laureck@users.sourceforge.net>     *
 *   (c) 2001                                                *
 *   You may copy, modify and redistribute this              *
 *   source file under the terms of the GNU Public License   *
 ************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mpeg.hh"
#include "mpegOut.hh"
#include "chunkTab.hh"

// declared in id3command.hh
extern int ParseID3Command(int argc, char** argv, int argc_offset);

// philipp
bool desperate_mode = false;
bool preserve_header = false;
bool print_progress = true;
// [L] ifdef the endMessage
#ifdef NEED_END_MESSAGE
void endMessage(void);
#endif

bool aspect_correction  = false;
byte forced_sequence_header = 0;

char* progname;
#ifndef NOSIGNAL_H
// for bug report
#include <signal.h>
#include <stdlib.h>
// for bug report

char** myargv;
int myargc;
c_char mpgtx_stack[mpgtx_stack_count];
int mpgtx_stack_current=0;

/*!
 * Callback for SIGSEGV, SIGBUS and SIGFPE.
 * prints a formated bug report, warns user and opens the bug report file
 *
 * @param signum catched signal: SIGSEGV, SIGBUS or SIGFPE
 */
void CatchBug(int signum)
{
	//print a formated bug report and warn user
	//open the bug report file
	FILE* bugreport;
	bugreport=fopen("bug.report","w+");

	//warn user
	fprintf(stderr,"BUG: Sorry you shouldn't read this...\n");
	fprintf(stderr,"Please help me to correct this and send a bug report\n");
	fprintf(stderr,"To send a bug report go to http://mpgtx.sourceforge.net\n");
	fprintf(stderr,"and click the submit new bug link (top right)\n");
	fprintf(stderr,"you can send it to <laureck@users.sourceforge.net> either\n");

	if (!bugreport) {
		bugreport=stderr;
		fprintf(stderr,"Please Include the following lines and the program output in the bug report\n");
		fprintf(stderr,  "---------------------------------------------------------------------------\n");
	}else{
		fprintf(stderr,"Please include the file \"bug.report\" and the program output in the bug report\n");
	}

	//start of bug report
	//version
	fprintf(bugreport,"%s version %s\n",progname,MPGTX_VERSION);

	// arguments to the program
	fprintf(bugreport,"args : ");
	for (int i=0; i < myargc; i++){
		fprintf (bugreport,"%s ",myargv[i]);
	}
	fprintf(bugreport,"\n");

	//what killed me
	switch(signum){
		case SIGSEGV: fprintf(bugreport,"SIGSEGV");break;
		case SIGBUS: fprintf(bugreport,"SIGBUS");break;
		case SIGFPE: fprintf(bugreport,"SIGFPE");break;
	}
	fprintf(bugreport," received\n");

	//print the calling stack
	fprintf(bugreport,"stack : ");
	for (int j=0; j <mpgtx_stack_count; j++){
		if (mpgtx_stack[(mpgtx_stack_current+j)%mpgtx_stack_count]!=0)
			fprintf(bugreport,"[%s] ",mpgtx_stack[(mpgtx_stack_current+j)%mpgtx_stack_count]);
	}
	fprintf(bugreport,"\nstack current: %d\n",mpgtx_stack_current);



	fclose(bugreport);
	exit(1);
}

/*!
 * Callback for SIGINT.
 *
 * @param signum unused
 */
void CatchBreak(int signum) {
	fprintf(stderr,"\nHave a Nice Day\n");
	exit(1);
}
#endif

#ifdef ENABLE_OPTIMIZATION
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>

struct timeval tv;
struct timezone tz;
double MainClockStart;

double Clock_Now(){
	double time_now;
	gettimeofday(&tv,&tz);
	time_now=tv.tv_sec + 0.000001 * tv.tv_usec;

	gettimeofday(&tv,&tz);
	functions_cummulated_time[SELF]+=2*((tv.tv_sec + 0.000001 * tv.tv_usec)-time_now);
	return tv.tv_sec + 0.000001 * tv.tv_usec;
}

void   AddTime(double timestart, int function){
	functions_cummulated_time[function]+= Clock_Now()-timestart;
}

double functions_cummulated_time[N_FUNCTIONS];
void init_cummulated_time(){
	MainClockStart=Clock_Now();
	atexit(PrintTime);
	for (int i=0; i <N_FUNCTIONS; i++){
		functions_cummulated_time[i]=0.0;
	}
}

void PrintTime(){
	AddTime(MainClockStart,MAIN);
	printf("-------------------------\n");
	printf("Time passed in main %.4f s\n",functions_cummulated_time[MAIN]);
	printf("\t(f)printf : %.4f s [%.2f%%]\n",
		functions_cummulated_time[PRINTF],
		functions_cummulated_time[PRINTF]*100.0/functions_cummulated_time[MAIN]);
	printf("\t  GetByte : %.4f s [%.2f%%]\n",
		functions_cummulated_time[GETBYTE],
		functions_cummulated_time[GETBYTE]*100.0/functions_cummulated_time[MAIN]);
	printf("\t     Copy : %.4f s [%.2f%%]\n",
		functions_cummulated_time[COPY],
		functions_cummulated_time[COPY]*100.0/functions_cummulated_time[MAIN]);
	printf("\tProfiling Time approx : %.4f [%.2f%%]\n",
		functions_cummulated_time[SELF],
		functions_cummulated_time[SELF]*100.0/functions_cummulated_time[MAIN]);
	
	
}

#endif



typedef enum argtype {file,option,range,none};
typedef enum programname {mpgsplit,mpgcat,mpgjoin,mpginfo,mpgdemux,other,mp3tag};



void print_help(programname invocation){
	BTRACK;
	switch(invocation)
	{
		case mpgsplit:
			printf("mpgsplit : split mpeg files into playable chunks\n");
			break;
		case mpgcat:
			printf("mpgcat   : cat mpeg files to standard output\n");
			break;
		case mpgjoin:
			printf("mpgjoin  : join compatible mpeg files into one\n");
			break;
		case mpgdemux:
			printf("mpgdemux : demultiplex elementary streams from a composite mpeg file\n");
			printf("Usage    : mpgdemux [options] composite_file \n");
			break;
		case mpginfo:
			printf("mpginfo  : print informations about mpeg files\n");
			printf("Usage    : mpginfo file [file...]\n");
			printf("Options  :\n");
			printf("  -N              Do not check timeline (save some time).\n");
			return;
			break;
		default :
			printf("%s : manipulate mpeg files\n",progname);
			break;
	}

	if (invocation != mpgdemux)
		printf("Usage    : %s [command] [options] [mpegfile [mpegfile | range]...\n",progname);
	printf("Commands :\n");

	if(invocation==other)
	{
		printf("  -i              print infos about following files.\n");
		printf("  -s              split following files according to the specified ranges.\n");
		printf("  -j              join  following files (ranges may be specified).\n");
		printf("  -d              demultiplex elementary streams from following file\n");
		printf("  -T              modify id3 tag.\n");
	}
	printf("  -h              print this help screen.\n");
	printf("  -v              print version informations.\n");
	if (invocation==other || invocation == mpgsplit)
		printf("  -#              where # is a number, split the following file in #.\n");
	if (invocation != mpgcat){
		printf("Options  :\n");
		printf("  -N              Do not print out excessive information while processing\n");
		printf("                  If you use MacOS Classic, this is RECOMMENDED\n");
		printf("                  Otherwise mpgtx will be dead slow!\n");
		printf("  -f              force overwriting of files, don't ask for confirmation\n");
		printf("  -P              keep headers of mpegs which sometimes is usefull\n");
		printf("  -X              Try to search for a valid PACK header in the whole file.\n");
		printf("                  Additionally option -N suppress output during search.\n");
		printf("                  This may result in an endless loop if not successfull!\n");
		printf("  -An             While joining or splitting, aspect ratio will be forced to:\n");
		printf("                  n=1 -> 1:1, n=2 -> 4:3, n=3 -> 16:9, n=4 -> 2.21:1 \n");
		printf("                  All Numbers from 0 - 16 will be accepted but the above are valid!\n"); 
		if (invocation != mpgjoin)
			printf("  -b NAME         set the basename for the output files\n");
		if (invocation != mpgsplit && invocation != mpgdemux){
			printf("  -o FILE         set the output file name (join implied)\n");
			printf("                  if FILE is - , standard output will be used\n");
			printf("  --force         force joining of incompatible files\n");
		}
		printf("  --no-parachute  don't try to catch SIGSEGV (usefull for debugging)\n");
	}
	if (invocation==mpgdemux) return;
	printf("Ranges   :\n");
	printf("  Ranges must follow an mpeg file\n");
	printf("  [a-b]           from 'a' inclusive to 'b' inclusive. If you want half opened\n");
	printf("                  ranges, you may want to use ]a-b], [a-b[ or ]a-b[ instead\n");
	printf("  [num/total]     the 'num' part if the mpeg file was split in 'total'.\n");
	printf("                  [1/4] would result in the first quarter of the mpeg file.\n");
	if (invocation !=mpgjoin){
		printf("  {a-b-...}       where 'a', 'b', ... are in ascending order. Split the file\n");
		printf("                  at given values. {700M} is therefore equivalent to ranges\n");
		printf("                  [-700M] ]700M-]\n");
	}
	printf("Values   :\n");
	printf("  Values can be time or offsets in the mpeg file\n");
	printf("  Time Format     HH:MM:SS where the HH: part can be omited\n");
	printf("  Offset Format   a number optionally followed by:\n");
	printf("                    M : offset is in Megabytes\n");
	printf("                    k : offset is in Kilobytes\n");
	printf("  An empty value means the corresponding file boundary:\n");
	printf("                  [-10M]  the first 10 Megabytes of file\n");
	printf("                  [500M-] from 500 Megabytes to the end of file\n");
	return;
}

// added 22 March 2001 to get rid of unistd (portability)
int mpgtx_access(char* filename){
	BTRACK;
	// returns 0 if file exist (readable)
	// returns 1 if not.
	FILE* test_file = fopen(filename,"r+");
	if (test_file == NULL) {
		return 1;
	}
	else {
		fclose(test_file);
		return 0;
	}
}



int main (int argc,char** argv){
#ifndef NOSIGNAL_H
	signal(SIGBUS,CatchBug);
	signal(SIGSEGV,CatchBug);
	signal(SIGFPE,CatchBug);
	signal(SIGINT,CatchBreak);
	for (int k=0; k < mpgtx_stack_count; k++) mpgtx_stack[k]=0;
	BTRACK;
	myargv=argv;
	myargc=argc;
#endif

#ifdef ENABLE_OPTIMIZATION
	init_cummulated_time();
#endif

	mpegOutFactory TheFac;
	chunkTab Tab(20);
	//char* current_filename=0;
	mpegOut* current_out;
	char* number;
	char* mybasename=0;
	char* myoutfile=0;
	chunk** ChunkTab;
	int ChunkCount;
	int nparts;
	char answer;
	bool want_info=false;
	bool basename_specified=false;
	bool joined=false;
	bool inparts=false;
	bool opresent=false;
	bool confirm_files=true;
	bool Id3Tag=false;
	bool force_option=false;
	bool catch_sigsegv=true;
	argtype lastarg=none;
	programname invocation;
	bool demux=false;
	int tmp_seq;
	FILE *tmp_file=NULL;



	////////////////////////////////////////
	//    Parse the program name          //
	////////////////////////////////////////
	ATRACK("parse progname");
	int i;
	int length=strlen(argv[0]);
	int start=0;

	for ( i = length-1; i >= 0; i--)
	{
		if((argv[0][i] == '/') || (argv[0][i] == '\\'))
		{
			start = i + 1;
			break;
		}
	}

	progname=new char[length-start+1];
	strcpy(progname,&argv[0][start]);
	if (!strcmp(progname,"mpgsplit")){
		invocation=mpgsplit;
		inparts=true;
	} else {
		if (!strcmp(progname,"mpgcat"))
		{
			invocation=mpgcat;
			joined=true;
			opresent=true;
			myoutfile=new char[2];
			myoutfile[0]='-';
			myoutfile[1]=0;
		}
		else {
			if (!strcmp(progname,"mpgjoin")){
				invocation=mpgjoin;
				joined=true;
			}
			else{
				if (!strcmp(progname,"mpginfo")){
					invocation=mpginfo;
					want_info=true;
				}
				else {
					if (!strcmp(progname,"mpgdemux")){
						invocation=mpgdemux;
						demux=true;
					}
					else{
						if (!strcmp(progname,"tagmp3")){
							return ParseID3Command(argc,argv,1);
						}
						else{

							invocation=other;
						}

					}
				}
			}
		}
	}


	// Warn user.
	/*fprintf(stderr,"%s version %s\n"
	  "THIS IS *BETA* SOFTWARE I really need your help to correct all remaining bugs.\n"
	  "If you find any bug in this program you are encouraged to post a bug report on\n"
	  "mpgtx homepage <http://mpgtx.sourceforge.net>.Thanks in advance for your help.\n\n"
	  ,progname,MPGTX_VERSION);

	 */
	///////////////////////////////////////
	//   Parse remaining args           //
	/////////////////////////////////////
	ATRACK("Parse Args");
	for ( i=1; i<argc; i++){
		switch(argv[i][0])
		{
			case '-':
				// this is an option
				if (lastarg==file && (!want_info)){
					// an option following a filename
					// appy range [0-100%]
					Tab.ParseRange("]0-]");
				}
				lastarg=option;
				if((argv[i][1] > '0')&&(argv[i][1]<='9')) {
					number=&argv[i][1];
					sscanf(number,"%d",&nparts);
					if(i+1>=argc){
						fprintf(stderr,"%s option used without a filename\n",argv[i]);
						return 1;
					}
					if(!Tab.AddFile(argv[++i])){
						fprintf(stderr,"%s is not a valid mpeg file\n",argv[i-1]);
						if(!want_info) return 1;
					}
					Tab.Nchunks(nparts);
					inparts=true;
				}
				else {
					switch (argv[i][1]){
						case 'd' :
							demux=true;
							break;
						case 'X' :
							desperate_mode =true;
							break;
						case 'P' :
							preserve_header = true;
							break;
						case 'N':
							print_progress = false;
							break;
						case 'A':
							aspect_correction = true;
							tmp_seq = -1;
							sscanf(&(argv[i][2]),"%d",&tmp_seq);
							if ((tmp_seq < 0 ) || (tmp_seq > 15))
							{
								fprintf(stderr,"invalid Value for aspect correction %d, exit!\n",tmp_seq);
								exit(1);
							}
							forced_sequence_header = tmp_seq << 4;
							break;

						case 'h' : print_help(invocation);
									return 0;
									break;
						case 'i' :
									want_info=true;
									break;
						case 'f' :
									confirm_files=false;
									break;
						case 's' :
									inparts=true;
									break;

						case 'j' :
									joined=true;
									if(!myoutfile) myoutfile="output.mpg";
									break;
						case 'T' :
									Id3Tag=true;
									return ParseID3Command(argc,argv,i+1);
									break;
						case 'b' :
									inparts=true;
									if (joined) {
										fprintf(stderr,"-o and -b options are mutually exclusive\n");
										return 1;
									} else { if (basename_specified) {
										fprintf(stderr,"only one basename is allowed\n");
										return 1;
									}
									basename_specified=true;
									if(i+1>=argc){
										fprintf(stderr,"-b option used without basename\n");
										return 1;
									}
									else {
										//TODO copy basename
										i++;
										// fprintf(stderr,"option -b read, basename : %s\n",argv[i]);
										mybasename=new char [strlen(argv[i])+1];
										strcpy(mybasename,argv[i]);
									}
									}
									break;
						case 'o' :
									if (basename_specified) {
										fprintf(stderr,"-b and -o options are mutually exclusive\n");
										return 1;
									}
									else
									{
										if (opresent){
											fprintf(stderr,"only one -o option allowed\n");
											return 1;
										}
										opresent=true;
										if(i+1>=argc){
											fprintf(stderr,"-o option used without outfile name\n");
											return 1;
										}
										else {
											i++;
											// fprintf(stderr,"option -o read, will join all in file : %s\n",argv[i]);
											myoutfile=new char [strlen(argv[i])+1];
											strcpy(myoutfile,argv[i]);
										}
									}
									break;
						case 'v':
									printf("%s Version %s\n",progname,MPGTX_VERSION);
									printf("Copyleft 2001 Laurent Alacoque <laureck@users.sourceforge.net>\n");
									printf("Partial work 2002 by Philipp Biermann <mpegcut@biermann.org>\n");
									printf("updates, bugs, patch, money :    http://mpgtx.sourceforge.net\n");
									return 0;
									break;
						case '-':
									// this is a long option (--xxxx)
									if (strcmp(argv[i],"--force")==0) force_option=true;
									if (strcmp(argv[i],"--no-parachute")==0) catch_sigsegv=false;
									break;
						default:
									fprintf(stderr,"unrecognized option %s\n",argv[i]);
									return 1;
									break;
					}
				}
				break;

			case ']':
			case '[':
				// this could be a range or a filename beginning with bracket
				// so check if it is not a file in current dir
				tmp_file=fopen(argv[i],"r");
				if(tmp_file==NULL){
					//	this is a range
					lastarg=range;
					if(!Tab.ParseRange(argv[i])){
						return 1;
					}
				}
				else{
					//	might be an input file, check!
					if (lastarg==file && !(want_info)){
						// two file arguments encountered, apply 100% range to the first
						// one
						Tab.ParseRange("]0-]");
					}
					if(tmp_file)
						fclose(tmp_file);
					lastarg=file;
					if(!Tab.AddFile(argv[i])){
						fprintf(stderr,"%s is not a valid mpeg file\n",argv[i]);
						if(!want_info) return 1;
					}
				}
				break;

			case '{':
				// comma separated list of boundaries
				lastarg=range;
				if(!Tab.ParseBoundaries(argv[i])){
					return 1;
				}
				break;
			default:
				// might be an input file, check!
				if (lastarg==file && !(want_info)){
					// two file arguments encountered, apply 100% range to the first
					//one
					Tab.ParseRange("]0-]");
				}
				lastarg=file;
				if(!Tab.AddFile(argv[i])) {
					fprintf(stderr,"%s is not a valid mpeg file\n",argv[i]);
					if(!want_info) return 1;
				}

		}


	}//for
	if (lastarg==file && (!want_info)){
		//range's missing
		Tab.ParseRange("]0-]");
	}

	///////////////////////////////////////////////////////////////////
	//                      Args are parsed
	///////////////////////////////////////////////////////////////////

#ifndef NOSIGNAL_H
	if (!catch_sigsegv){
		// if the --no-parachute was used, restore the default behaviour
		signal(SIGBUS,SIG_DFL);
		signal(SIGSEGV,SIG_DFL);
		signal(SIGFPE,SIG_DFL);
		signal(SIGINT,SIG_DFL);
	}
#endif





	ChunkTab = Tab.GetChunks(&ChunkCount);


#ifdef _DEBUG_
	Tab.PrintTab();
#endif
	ATRACK("handling info mode");
	/////////////////////////////////////////////////////////////////
	// Handle Info mode
	/////////////////////////////////////////////////////////////////

	if (want_info){
		Tab.PrintInfos();
#ifdef NEED_END_MESSAGE
		endMessage();
#endif
		return 0;
	}

	ChunkTab=Tab.GetChunks(&ChunkCount);
	// from here we need at least one chunk
	if (ChunkCount==0){
		fprintf(stderr,"nothing to do \n");
		return 0;
	}
	RTRACK;
	ATRACK("demux mode");
	/////////////////////////////////////////////////////////////////
	// Handle demux mode
	/////////////////////////////////////////////////////////////////
	if (demux){
		if (ChunkCount!=1){
			fprintf(stderr,"demux currently requires exactly one mpeg file\n");
			return 1;
		}
		if (!basename_specified){
			fprintf(stderr,"No base name specified, defaulting to basename : chunk\n");
			mybasename="chunk";
		}
		demuxer Dmux(ChunkTab[0]->mpegfile, mybasename,confirm_files);
		Dmux.Process();
		//check the errors!
#ifdef NEED_END_MESSAGE
		endMessage();
#endif
		return 0;
	}
	// from here we need at least one chunk
	if (ChunkCount==0){
		fprintf(stderr,"nothing to do \n");
		return 0;
	}

	// Tab.PrintTab();
	RTRACK;
	ATRACK("join mode");
	/////////////////////////////////////////////////////////////////
	// All files are joined
	/////////////////////////////////////////////////////////////////
	if (joined) {
		if (!opresent) {
			myoutfile = new char[500];
			if (ChunkTab[0]->mpegfile->has_video() == false)
				sprintf(myoutfile, "chunk.mp3");
			else
				sprintf(myoutfile, "chunk.mpg");
		}
		if (ChunkCount >1) {
			for ( i = 1; i < ChunkCount ; i++)
			{
				if(!ChunkTab[0]->mpegfile->Match(ChunkTab[i]->mpegfile))
				{
					if (force_option)
						fprintf(stderr, "Specified files don't seem to be compatible\n");
					else {
						fprintf(stderr, "Specified files are not compatible, if you still want to join them use --force switch\n");
						return 1;
					}
				}
				//okay they match
			}
		}
		if (!strcmp(myoutfile,"-")){
			//output to stdout
			current_out=TheFac.NewMpegFrom(ChunkTab[0]->mpegfile,stdout);
			if (!current_out){
				fprintf(stderr,"\nFatal : could not process file\n");
			}
		}
		else {
			//output to myoutfile
			// if (!force_action)
			if (confirm_files && !mpgtx_access(myoutfile))
			{
				fprintf(stderr,"file %s already exist. erase ? [n/y/a]:", myoutfile);
				fflush(stderr);
				answer=getchar();
				while (getchar() != '\n'); //flush the leading \n
				if (answer!='y' && answer !='Y' && answer != 'a' && answer != 'A') {
					fprintf(stderr,"Aborted\n");
					return 0;
				}
				if (answer == 'a' || answer == 'A') confirm_files = false;
			}
			current_out = TheFac.NewMpegFrom(ChunkTab[0]->mpegfile, myoutfile);
			if (!current_out)
				fprintf(stderr,"\nFatal : could not process file %s\n",myoutfile);
		}
		if (!current_out){
			//something went wrong
			return 0;
		}

		for ( i=0;i<ChunkCount;i++)
		{
			fprintf(stderr,"Now processing %s %d/%d ...  ",
				ChunkTab[i]->mpegfile->FileName, i+1, ChunkCount);
			fflush(stderr);
			if (!current_out->WriteChunk(ChunkTab[i]->mpegfile, ChunkTab[i]->from,
						ChunkTab[i]->from_included, ChunkTab[i]->to, ChunkTab[i]->to_included))
				fprintf (stderr," failed, range results in an empty chunk\n");
			else
				fprintf(stderr,"\n");
		}
		current_out->Finish();
#ifdef NEED_END_MESSAGE
		endMessage();
#endif
		return 0;
	}

	if (inparts) {
		RTRACK;
		ATRACK("split mode");
		/////////////////////////////////////////////////////////////////
		// each chunk in one file
		/////////////////////////////////////////////////////////////////
		int myprec;
		char sChunkCount[50];
		//write ChunkCount as a string
		sprintf(sChunkCount,"%d", ChunkCount + 1);
		//now we now how many digits we need -> in myprec
		myprec = strlen(sChunkCount);

		if (!basename_specified) {
			if (!opresent)
				//neither -o nor -b, use default basename
				mybasename="chunk";
			else
			{
				if (ChunkCount >1){
					fprintf(stderr,"-o option invalid for %d output files\n",ChunkCount);
					return 1;
				}
				mybasename = new char[strlen(myoutfile)+1];
				strcpy(mybasename, myoutfile);
			}
		}

		myoutfile = new char[500];
		for (i = 0;i < ChunkCount; i++)
		{
			//compute the name
			if (ChunkTab[i]->mpegfile->has_video()==false)
			{
				if (opresent)
					sprintf(myoutfile,"%s",mybasename);
				else
				{
					if (ChunkCount==1)
						sprintf(myoutfile,"%s.mp3",mybasename);
					else 
						sprintf(myoutfile,"%s-%0*d.mp3",mybasename,myprec,i+1);
				}
			}
			else
			{
				if (opresent)
					sprintf(myoutfile,"%s",mybasename);
				else
				{
					if (ChunkCount==1)
						sprintf(myoutfile,"%s.mpg",mybasename);
					else 
						sprintf(myoutfile,"%s-%0*d.mpg",mybasename,myprec,i+1);
				}
			}	
			if (confirm_files && !mpgtx_access(myoutfile))
			{
				fprintf(stderr,"file %s already exist. erase ?"
						" [n/y/a]:",myoutfile);
				fflush(stderr);
				answer=getchar();
				while (getchar() != '\n'); //flush the leading \n
				if (answer != 'y' && answer != 'Y' && answer != 'a' && answer != 'A') {
					fprintf(stderr,"Aborted\n");
					return 0;
				}
				if (answer == 'a' || answer == 'A') confirm_files = false;

			}

			current_out = TheFac.NewMpegFrom(ChunkTab[0]->mpegfile, myoutfile);
			if (!current_out) {
				fprintf(stderr,"\nFatal : could not process %s\n", myoutfile);
				return 1;
			}
			fprintf(stderr,"Now processing %s [%d/%d] ...  ",
				ChunkTab[i]->mpegfile->FileName, i+1, ChunkCount);
			fflush(stderr);
			if (!current_out->WriteChunk(ChunkTab[i]->mpegfile, ChunkTab[i]->from,
						ChunkTab[i]->from_included, ChunkTab[i]->to, ChunkTab[i]->to_included))
				fprintf (stderr,"  failed, range results in an empty chunk\n");
			else
				fprintf(stderr,"\n");
			current_out->Finish();
		} // for
		delete [] myoutfile;
#ifdef NEED_END_MESSAGE
		endMessage();
#endif
		return 0;
	}

	//no action were taken
	fprintf(stdout, "You must choose one options between -i -s -j\n");
	fprintf(stdout, "Type %s -h for help\n", progname);
	return 0;
}

#ifdef NEED_END_MESSAGE
void endMessage(void) {
		fprintf(stderr,"-------Done--------\n");
}
#endif
