
/* pana_driver.c : routines for PANA_OMDR videodisc player */

#include <stdio.h>
#include "pana.h"
#include "rpd_driver.h"

#include "hash.h"

#define MAXRETRYS 0		/* the number of times we try before giving up */

extern int ttyutil_debug;

int		pana_debug = 0;
static	UBYTE	inbytes[32];
static	UBYTE	outbytes[32];

static HashTablePtr	pana_htp = NULL;	/* contains all commands */

/* ------------------------------------------------------------------------ */

static int
pana_FillTable()	/* must be called first! */
{
int	i;

	if( pana_htp )
		return -1;
	pana_htp = hash_create( "Panasonic-OMDR commands", 50 );
	for( i=0; i<NUM_PANA_CMDS; i++ )
		hash_install( pana_htp, pana_table[i].cmd_name, NULL, i );
	return 0;
}

/* ------------------------------------------------------------------------ */

int
pana_lookup( cmdstr )	/* convert command name in pana.h into pana_table index */
	char *cmdstr;
{
HashNodePtr np;

	if( !cmdstr )
		return -1;
	np = hash_lookup( pana_htp, cmdstr );
	if( !np )
		return -1;
	return np->def;
}

/* ------------------------------------------------------------------------ */

pana_cmd(rpd,num)

	RPD_ptr	rpd;
	int 	num;
{
static char *funcname = "pana_cmd";
int	success = 0;
int	r1, r2;

	/* note that with the audio, must set the bits corresponding
	   to the current state of the software */

	switch(num)
	{
		case INDEX_ON:
			if( !pana_ttyio( rpd->fd, pana_lookup("Index-On"), 
				0,0, &r1, &r2, 1 ) )
			{
				rpd->state.indexon = 1;
				success = 1;
			}
			break;
		case INDEX_OFF:
			if( !pana_ttyio( rpd->fd, pana_lookup("Index-Off"),
				0,0, &r1, &r2, 1 ) )
			{
				rpd->state.indexon = 0;
				success = 1;
			}
			break;
		case A1_ON:
/*			pana_ttyio( rpd->fd, pana_lookup("Play-Audio-On"),
				0,0, &r1, &r2, 1 ); */
			if( !pana_ttyio( rpd->fd, pana_lookup("A1-On"),
				0,0, &r1, &r2, 1 ) )
			{
				rpd->state.audio1_on = 1;
				success = 1;
			}
			break;
		case A1_OFF:
/*			pana_ttyio( rpd->fd, pana_lookup("Play-Audio-On"),
				0,0, &r1, &r2, 1 ); */
			if( !pana_ttyio( rpd->fd, pana_lookup("A1-Off"),
				0,0, &r1, &r2, 1 ) )
			{
				rpd->state.audio1_on = 0;
				success = 1;
			}
			break;
		case A2_ON:
/*			pana_ttyio( rpd->fd, pana_lookup("Play-Audio-On"),
				0,0, &r1, &r2, 1 ); */
			if( !pana_ttyio( rpd->fd, pana_lookup("A2-On"),
				0,0, &r1, &r2, 1 ) )
			{
				rpd->state.audio2_on = 1;
				success = 1;
			}
			break;
		case A2_OFF:
/*			pana_ttyio( rpd->fd, pana_lookup("Play-Audio-On"),
				0,0, &r1, &r2, 1 ); */
			if( !pana_ttyio( rpd->fd, pana_lookup("A2-Off"),
				0,0, &r1, &r2, 1 ) )
			{
				rpd->state.audio2_on = 0;
				success = 1;
			}
			break;
		case LOAD:
			if( !pana_ttyio( rpd->fd, pana_lookup("Load"),
				0,0, &r1, &r2, 1 ) )
			{
				rpd->state.volume_loaded = 1;
				success = 1;
			}
			else
			{
				fprintf(stderr,"%s: load failure\n",rpd->devname);
				rpd->state.volume_loaded = 0;
			}
			break;
		case UNLOAD:
			if( !pana_ttyio( rpd->fd, pana_lookup("Eject"),
				0,0, &r1, &r2, 1 ) )
			{
				rpd->state.volume_loaded = 0;
				rpd->volume[0] = 0;
				success = 1;
			}
			else
			{
				fprintf(stderr,"%s: unload failure\n",rpd->devname);
			}
			break;
		default:
			fprintf(stderr,"%s: %s: illegal request %d\n",
				rpd->devname,funcname,num);
			break;
	}

	if( success )
		return(0);
	else
		return -1;
}

/* ------------------------------------------------------------------------ */

pana_varspeed(rpd,num)

	RPD_ptr	rpd;
	int	num;
{
static char *funcname = "pana_varspeed";
int	speed;
int	loc;	/* index in pana_table */
int	r1, r2;

	switch(num)
	{
		case R_MAX:
			speed = 10;
			loc = pana_lookup("Rev-Fast");
			break;
		case R_VERY_FAST:
			speed = 7;
			loc = pana_lookup("Rev-Fast");
			break;
		case R_FAST:
			speed = 3;
			loc = pana_lookup("Rev-Fast");
			break;
		case R_PLAY:
			loc = pana_lookup("Rev-Play");
			break;
		case R_SLOW:
			speed = 5;
			loc = pana_lookup("Rev-Slow");
			break;
		case R_VERY_SLOW:
			speed = 10;
			loc = pana_lookup("Rev-Slow");
			break;
		case STOP:
			loc = pana_lookup("Clear");
			break;
		case F_VERY_SLOW:
			speed = 10;
			loc = pana_lookup("Fwd-Slow");
			break;
		case F_SLOW:
			speed = 5;
			loc = pana_lookup("Fwd-Slow");
			break;
		case F_PLAY:
			loc = pana_lookup("Fwd-Play");
			break;
		case F_FAST:
			speed = 3;
			loc = pana_lookup("Fwd-Fast");
			break;
		case F_VERY_FAST:
			speed = 7;
			loc = pana_lookup("Fwd-Fast");
			break;
		case F_MAX:
			speed = 10;
			loc = pana_lookup("Fwd-Fast");
			break;
		default:
		fprintf(stderr,"%s: %s: illegal cmd %d\n",
			rpd->devname,funcname,num);
			return(-1);
			break;
	}

	if( !pana_ttyio(rpd->fd, loc, speed,0, &r1, &r2, 1 ) )
		return 0;
	else
		return -1;
}

/* ------------------------------------------------------------------- */

pana_jog(rpd,num)

	RPD_ptr	rpd;
	int	num;
{
static char *funcname = "pana_jog";
int	r1,r2;
int	loc;
int	i;

	if( num==0 )
		return 0;
	if( num<0 ) 
	{
		num = (-num);
		loc = pana_lookup("Step-Rev");
	}
	else
		loc = pana_lookup("Step-Fwd");

	for( i=0; i<abs(num); i++ )
	{
		if( pana_ttyio(rpd->fd, loc, 0,0, &r1, &r2, 1) )
			return -1;
	}
	return 0;
}

/* ------------------------------------------------------------------------ */

pana_getframe(rpd)

	RPD_ptr	rpd;
{
static char *funcname = "pana_getframe";
int	success = 0;
int	frame;
int	r1, r2;

	if( pana_ttyio(rpd->fd, pana_lookup("GetFrame"), 0,0, &frame, &r2, 1) )
	{
		fprintf(stderr,"%s: %s: can't get player status\n",
			rpd->devname,funcname);
		return -1;
	}
	else
		return frame;
}

/* ------------------------------------------------------------------------ */

pana_search(rpd,frame,wait)
	RPD_ptr	rpd;
	int	frame;
	int	wait;		/* if true, hangs until it gets there 
					or times out */
{
static char *funcname = "pana_search";
int	success = 0;
int	r1, r2;
int	dir;

	if( !pana_ttyio(rpd->fd, pana_lookup("Search"), frame, 0, &r1, &r2, wait) )
		return(0);
	else
		return -1;
}

/* ------------------------------------------------------------------------ */

pana_reset(rpd)

	RPD_ptr	rpd;
{
static char *funcname = "pana_reset";
int	ret = 0;
int	Timer = 0;

	pana_varspeed(rpd,STOP);
	
	if( pana_getframe(rpd) < 0 )
	{
		rpd->state.volume_loaded = 0;
		rpd->state.not_responding = 1;
	}
	else
	{
		rpd->state.volume_loaded = 1;
		rpd->state.not_responding = 0;
	}
	
	if( !rpd->state.volume_loaded )
	{
		if( pana_cmd(rpd,LOAD) )
		{
			ret = -1;
			rpd->state.volume_loaded = 0;
		}
		else
		{
			rpd->state.volume_loaded = 1;

			/* now get the disc spinning, and put it on frame 1 */

			set_timeout(27000,&Timer);
			while( Timer != 1 && pana_varspeed(rpd,F_PLAY) )
				mpause(2000);
			if( Timer == 1 )
				ret = -1;
			pana_varspeed(rpd,STOP);
			pana_search(rpd,1,1);
			set_timeout(0,&Timer);
		}
	}

	if( pana_cmd(rpd,INDEX_OFF) )
		ret = -1;
/*
	if( pana_cmd(rpd,A1_ON) )
		ret = -1;
	if( pana_cmd(rpd,A2_ON) )
		ret = -1;
*/
	if( ret < 0 )
	{
		rpd->state.not_responding = 1;
		fprintf(stderr,"rpd '%s' not responding\n",rpd->devname);
	}
	else
		rpd->state.not_responding = 0;
	return ret;
}

/* ------------------------------------------------------------------------ */

pana_segplay(rpd,f1,f2,wait)

	RPD_ptr	rpd;
	int	f1,f2;
	int	wait;		/* if true, hangs until done */
{
static char *funcname = "pana_segplay";
int	fail = 0;
int	r1,r2;
int	len;
int	timeout;
int	readnum;
int	i;
int	res;

	len = abs(f2-f1);

	if( pana_search(rpd,f1,1) )	/* must wait for now */
	{
		fprintf(stderr,"%s: %s: couldn't search to %d\n",
			rpd->devname,funcname,f1);
		return -1;
	}

	if( !pana_ttyio(rpd->fd,pana_lookup("Fwd-Play-To"), f2,0, &r1,&r2, 0) )
	{
		if( !wait )
			return 0;
		else
		{
			readnum = 4;	/* STX + ETX + 2 chars */
			timeout = 33*len;
			res = ttyutil_read(rpd->fd,inbytes,readnum,timeout+1000);
/*	
			printf("segplay response:\n");
			for( i=0; i<readnum; i++ )
				printf("[%02x] ",inbytes[i]);
			printf("\n");
*/
			if( res == -2 )
			{
				fprintf(stderr,"%s: %s: timed out\n",
					rpd->devname, funcname );
				fail = 1;
			}
			else if( res == -1 )
			{
				fprintf(stderr,"%s: %s: read error\n",
					rpd->devname, funcname );
				fail = 1;
			}
			else if( res != readnum )
			{
				fprintf(stderr,"%s: %s: read %d chars, not %d\n",
					rpd->devname, funcname,res,readnum );
				fail = 1;
			}
			if( inbytes[0] != PANA_BEGIN || inbytes[1] == 'E' )
			{
				fprintf(stderr,"%s: %s: bad response\n",
					rpd->devname, funcname);
				fail = 1;
			}
		}
	}

	if( fail )
		return -1;
	else
		return 0;
}

/* ------------------------------------------------------------------------ */

pana_ttyio( fd, loc, parm1, parm2, ip1, ip2, wait )

	int	fd;
	int	loc;
	int	parm1, parm2;
	int *	ip1;
	int *	ip2;
	int	wait;		/* if true, wait for the reply */
{
static char *funcname = "pana_ttyio";
static int	retry = 0;
int	writenum, readnum;
int	timeout = 500;
int	num = 0;
static char	outpacket[128];

	ttyutil_debug = pana_debug;

	if( loc < 0 )
	{
		fprintf(stderr,"%s: bad table index %d\n",funcname,loc);
		return -1;
	}

	sprintf(outbytes, pana_table[loc].cmd_fmt, parm1, parm2 );
	sprintf(outpacket, "%c%s%c", PANA_BEGIN, outbytes, PANA_END );	

	writenum = strlen(outpacket);
	ttyutil_clear(fd);		/* flush input; maybe a mistake ... */

	if( ttyutil_write( fd,outpacket,writenum,0 ) == -1 )
		return (-1);

	readnum = pana_table[loc].nresp+2;	/* STX + readbytes + ETX */
	if( readnum == 0 || !wait )
		return (0);

	if( loc == pana_lookup("Load") || loc == pana_lookup("Eject") )
		timeout = 20000;
	else if( loc == pana_lookup("Search") )
		timeout = 2000;
	else
		timeout = 500;
	
	if( (num=ttyutil_read(fd,inbytes,readnum,timeout)) == -1 )
		return (-1);

	if( num==-2 )	/* timeout condition */
	{
		if( pana_debug )
		{
			if( num == -2 )
				printf("%s: NO RESPONSE, try %d\n",
					funcname,retry+1);
			else
				printf("%s: ERROR RESPONSE, try %d\n",
					funcname,retry+1);
		}

		if( retry++ < MAXRETRYS )
		{
		int rv;

			rv = pana_ttyio( fd, loc, parm1, parm2, ip1, ip2, wait );
			retry = 0;
			return (rv);
		}
		else
		{
			retry = 0;
			fprintf(stderr,"%s: i/o timeout\n",funcname);
			return (-1);
		}
	}

	if( num != readnum )
	{
		fprintf(stderr,"%s: expected %d bytes, got %d\n",
			funcname,readnum,num);
		return -1;
	}

	if( readnum > 2 )	/* have a response */
	{
		if( inbytes[0] != PANA_BEGIN || inbytes[1] == 'E' )
			return -1;
		sscanf( inbytes+1, pana_table[loc].resp_fmt, ip1 );
	}
	
	return 0;
}

/* ------------------------------------------------------------------------ */

pana_setfuncs( disc )

	RPD_ptr	disc;
{
int	r1,r2;

	disc->reset = pana_reset;
	disc->cmd = pana_cmd;
	disc->search = pana_search;
	disc->segplay = pana_segplay;
	disc->getframe = pana_getframe;
	disc->varspeed = pana_varspeed;
	disc->jog = pana_jog;
	disc->record = NULL;
	pana_FillTable();

	if( !pana_ttyio(disc->fd, pana_lookup("On-Line-Mode"), 0,0, &r1,&r2, 1) )
		return 0;
	else
		return -1;
}


