/********************************************************
*
* r4d.c		Master Control Program for R4
*
* Author:	Gary Hoggard	26 Apr 1998
*
* Change History:
* 01 Jan 1999	enabled sound
* 02 Jan 1999	filtered processing of input cmds
********************************************************/

#include "r4.h"

static char buffer[BUFSIZ];	/* all-purpose buffer */

main()
	{
	char binpath[128];	/* pathname for binaries dir */
	char libpath[128];	/* pathname for library files */
	char filename[128];	/* pathname of file */
	int counter=0;		/* an all-purpose counter */

	int CMD;		/* file handle for command named-pipe */
	int JOY;		/* file handle for joystick named-pipe */
	int SNSR;		/* file handle for sensor named-pipe */
	FILE *DRV;		/* file handle for drive named-pipe */
	FILE *FACE;		/* file handle for face named-pipe */
	FILE *VOIC;		/* file handle for voice named-pipe */
	FILE *SND;		/* file handle for sound named-pipe */
	FILE *PIPE;

	/* get environment variables */
	if (getenv("DEBUG"))
		{
		debug=YES;
		dlog = fopen(DEBUGFILE, "a");
		}
	if (getenv("R4_BINARIES"))
		strcpy(binpath, getenv("R4_BINARIES"));
	else
		strcpy(binpath, BIN);
	if (getenv("R4_LIB"))
		strcpy(libpath, getenv("R4_LIB"));
	else
		strcpy(libpath, LIB);
	if (debug)
		{
		fprintf(dlog, "binpath='%s'\nlibpath='%s'\n", binpath, libpath);
		fflush(dlog);
		}

	/* spawn other programs */
	sprintf(filename, "%s/joystick", binpath);
	if (!fork()) { execl(filename, filename, NULL); exit(2); }
	sprintf(filename, "%s/sensor", binpath);
	if (!fork()) { execl(filename, filename, NULL); exit(2); }
	sprintf(filename, "%s/drive", binpath);
	if (!fork()) { execl(filename, filename, NULL); exit(2); }
	sprintf(filename, "%s/face", binpath);
	if (!fork()) { execl(filename, filename, NULL); exit(2); }
	sprintf(filename, "%s/voice", binpath);
	if (!fork()) { execl(filename, filename, NULL); exit(2); }
	sprintf(filename, "%s/sound", binpath);
	if (!fork()) { execl(filename, filename, NULL); exit(2); }
	if (debug)
		{
		fprintf(dlog, "programs spawned\n");
		fflush(dlog);
		}

	/* open the output named-pipes for writing */
	sprintf(filename, "%s/drive_pipe", libpath);
	if ((DRV = fopen(filename, "w")) == NULL)
		{ perror(filename); exit(1); }
	sprintf(filename, "%s/face_pipe", libpath);
	if ((FACE = fopen(filename, "w")) == NULL)
		{ perror(filename); exit(1); }
	sprintf(filename, "%s/sound_pipe", libpath);
	if ((SND = fopen(filename, "w")) == NULL)
		{ perror(filename); exit(1); }
/*
	sprintf(filename, "%s/voice_pipe", libpath);
	if ((VOIC = fopen(filename, "w")) == NULL)
		{ perror(filename); exit(1); }
*/
	if (debug)
		{
		fprintf(dlog, "output pipes opened\n");
		fflush(dlog);
		}

	/* open the input named-pipes for reading */
	sprintf(filename, "%s/command_pipe", libpath);
	if ((CMD = open(filename, O_RDONLY|O_NDELAY)) == FAIL)
		{ perror(filename); exit(1); }
	sprintf(filename, "%s/joystick_pipe", libpath);
	if ((JOY = open(filename, O_RDONLY|O_NDELAY)) == FAIL)
		{ perror(filename); exit(1); }
	sprintf(filename, "%s/sensor_pipe", libpath);
	if ((SNSR = open(filename, O_RDONLY|O_NDELAY)) == FAIL)
		{ perror(filename); exit(1); }
	if (debug)
		{
		fprintf(dlog, "input pipes opened\n");
		fflush(dlog);
		}

	/* poll input pipes and control the world! (or at least the robot) */
	while (YES)
		{
		++counter;
		readpipe(SNSR);			/* stores results in buffer[] */
		if (! *buffer) readpipe(CMD);
		if (! *buffer) readpipe(JOY);
		if (debug)
			{
			fprintf(dlog, "read '%s' from input pipe\n", buffer);
			fflush(dlog);
			}
		if (*buffer)
			{
			switch (*buffer)
				{
				/* direct command routing: */
				case 'a':	PIPE = DRV;	break;
				case 'f':	PIPE = FACE;	break;
				case 't':	PIPE = FACE;	break;
				case 'm':	PIPE = DRV;	break;
				case 'p':	PIPE = SND;	break;
				case 'v':	PIPE = VOIC;	break;

				/* command processing required: */
				case 'j':		/* joystick switches */
					PIPE = SND;
					switch (atoi(&buffer[1]))
						{
						case 1: strcpy(buffer, "pwr2d2-1");
						case 2: strcpy(buffer, "pwr2d2-2");
						case 3: strcpy(buffer, "pwvader");
						}
					break;
				case 's':		/* sensor switches */
					break;
				}
			strcat(buffer, "\n");
			fputs(buffer, PIPE);
			fflush(PIPE);
			if (debug)
				{
				fprintf(dlog, "wrote '%s' to output pipe\n", buffer);
				fflush(dlog);
				}
			}
		pause_ms(100);
		if (counter > 50)
			{
			fputs("fblink\n", FACE);
			fflush(FACE);
			}
		}
	}

readpipe(int PIPE)
	{
	char c;
	int i = 0;

	if (debug)
		{
		fprintf(dlog, "entering readpipe(), fd=%d\n", PIPE);
		fflush(dlog);
		}
	while (read(PIPE, &c, 1) == 1)
		buffer[i++] = c;
	buffer[i] = '\0';
	if (debug)
		{
		fprintf(dlog, "returning from readpipe(), buffer='%s'\n", buffer);
		fflush(dlog);
		}
	return;
	}

pause_ms(int millisecs)
	{
	struct timeval timer;

	timer.tv_sec = millisecs / 1000;
	timer.tv_usec = (millisecs % 1000) * 1000;
	select(0, NULL, NULL, NULL, &timer);
	}

/*______________________end_of_r4d.c_____________________*/

