/*****************************************************************************/

/*
 *      playfile.c -- REALmagic trivial file player example
 *
 *      Copyright (C) 2000 Sigma Designs
 *                   written by Emmanuel Michon
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      This program is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*****************************************************************************/

#define _LARGEFILE64_SOURCE 1

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <termios.h>

#define _DEFINE_FMP_TYPES_
#include "fmp.h"

#define PLAYING 1
#define PAUSED 0

int peek = -1;
struct termios orig, new;

void open_port()
{
    if (tcgetattr(0,&orig)==-1) 
    {
        printf("Could not tcgetattr");
        exit(1);
    }

    new = orig;
	
    /* settings for raw mode */
    new.c_lflag     &= ~ICANON;
    new.c_lflag     &= ~ECHO;
    new.c_lflag     &= ~ISIG;
    new.c_cc[VMIN]  =  1;
    new.c_cc[VTIME] =  0;
	
    if (tcsetattr(0,TCSANOW,&new)==-1) 
    {
        printf("Could not tcsetattr");
        exit(1);
    }	
}

void close_port()
{
    tcsetattr(0, TCSANOW, &orig);
}
int kbhit()
{
    char ch;
    int  nread;

    if(peek != -1) return 1;

    new.c_cc[VMIN] = 0;
    tcsetattr(0, TCSANOW, &new);
    nread = read(0, &ch, 1);
    new.c_cc[VMIN] = 1;
    tcsetattr(0, TCSANOW, &new);

    if(nread == 1)
    {
        peek = ch;
        return 1;
    }

    return 0;
}

int readch()
{
    char ch;

    if(peek != -1)
    {
        ch   = peek;
        peek = -1;
        return ch;
    }

    read(0, &ch, 1);
    return ch;
}

DWORD setOutputMode(DWORD newvgatv)
{
  DWORD vgatv;
  vgatv = FMPGet(FMPI_VIDEOOUT);
  vgatv = vgatv  & (~FMPV_VIDEOOUT_MODE_MASK);
  vgatv = vgatv | newvgatv;
  return FMPSet(FMPI_VIDEOOUT, vgatv);
}

int main(int argc,char **argv)
{
	int fd;
	int streamtype;
	int bytesread=1,rc=FMPE_OK;
	int buf, playfile_state;
	int b_stopit = 0, b_getoutofit = 0;
	
	

	if (argc!=3) {
		fprintf(stderr,
			"Syntax is playfile <streamtype> <filename>\n"
			"<streamtype -> t (transport) d (dvd)   s (system)\n"
			"               p (program)   v (video) m (mpeg audio) a (mpeg2 ac3)>\n"
			"Example: ./playfile s /samplempeg/movie.mpg\n"
			"During the file playing use your keyboard:\n"
			" 'r' to rewind from the beginning,\n"
			" 'q' to stop, close and exit propely.\n"
			);
		exit(1);
	}

	switch (argv[1][0]) {
	case 't':
		streamtype=FMPF_TRANSPORT;
		break;
	case 'd':
		streamtype=FMPF_DVD;
		break;
	case 's':
		streamtype=FMPF_SYSTEM;
		break;
	case 'p':
	        streamtype=FMPF_PROGRAM;
		break;
	case 'v':
	        streamtype=FMPF_VIDEO;
		break;
	case 'm':
	        streamtype=FMPF_MPEG_AUDIO;
		break;
	case 'a':
	       streamtype=FMPF_AC3;
	       break;

	default:
	       fprintf(stderr,
		       "Syntax is playfile <streamtype> <filename>\n"
		       "<streamtype -> t (transport) d (dvd)   s (system)\n"
		       "               p (program)   v (video) m (mpeg audio) a (mpeg2 ac3)>\n"
		       "Example: ./playfile s /samplempeg/movie.mpg\n"
		       "During the file playing use your keyboard:\n"
		       " 'r' to rewind from the beginning,\n"
		       " 'q' to stop, close and exit propely.\n"
		       );
	       exit(1);
	}

	MPEGDriverEntry(NO_DRIVE);
	FMPOpen(streamtype,32*1024,10, NULL, 0);
	FMPPlay();

	setOutputMode(FMPV_VIDEOOUT_TV);

        fd=open(argv[2],O_RDONLY|O_LARGEFILE);
	if (fd==-1) {
		perror("open failed"); 
		exit(1); 
	}

	open_port();
	
	playfile_state = PLAYING;
	
	while (rc==FMPE_OK && !b_getoutofit) {
		while (bytesread && !b_stopit) {
			FMP_BUFFER FMPBuf;
			static int count=0;
			if(kbhit())
			  {
			    buf = readch();
			    switch(buf)
			      {
			      case 'r':
				b_stopit = 1;
				fprintf(stdout,">> Rewind ...\n");
				break;
			      case 'q':
				b_stopit = 1;
				b_getoutofit = 1;
				break;
			      default:
				break;
			      }
			  }
			// get a pointer to a free buffer
			rc = FMPGetBuffer (&FMPBuf, TRUE);
			if (rc != FMPE_OK) {
				printf ("FMPError : %s\n", FMPGetLastError(rc));
				break;
			}	
			
			// signals can cause harmless EINTR
			while (((bytesread=read(fd,FMPBuf.pBuffer,FMPBuf.dwBufferSize))==-1)
			       &&(errno==EINTR));
			if (bytesread==-1) bytesread=0;
			
			FMPBuf.dwDataSize=bytesread;
			
			// the buffer is ready to be queued
			FMPPush (&FMPBuf);
			
			count++;
#define ONEEVERY 20			
			if (count%ONEEVERY==0) printf("PTS %ld / STC %ld\n",
						      FMPGet (FMPI_PTS),
						      FMPGet (FMPI_STC));	
		  }
		FMPStop();
		FMPPlay();
		if(!b_getoutofit)
		  b_stopit = 0;
		lseek (fd,0,SEEK_SET);
		bytesread=1;
	}
	fprintf(stdout,">>Exited from playing loop !\n");
	close_port();
	close (fd);
	FMPStop();
	FMPClose();
	MPEGDriverUnload();
	fprintf(stdout,">>Driver is closed !\n");
	exit(0);
}
