/*
 * ---------------------------------------------------------------------------
 * sfxclient/main.c
 *
 * Copyright by Terry Evans 1994
 * tevans@cs.utah.edu, tevans@slc.unisys.com
 * ---------------------------------------------------------------------------
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer. 2.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ---------------------------------------------------------------------------
 */

#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>


#include "global.h"
#include "error.h"
#include "main.h"


/* The defines are from sfxserver/global.h */
int samples[MAX_SAMPLES];
int channels[MAX_CHANNELS];

void main(int argc, char **argv[])
{
  int pid;
  int nread;
  int pipe1[2] = { -1, -1 };
  int pipe2[2] = { -1, -1 };
  fd_set read_fd;

  char buffer[MAX_BUFFSIZE];
  int loop;

  /* Create the pipes */
  if(pipe(pipe1) != 0)
    E_ErrnoFatalError("main", "could not create pipe1");

  if(pipe(pipe2) != 0)
    E_ErrnoFatalError("main", "could not create pipe2");

  /* Check for an error */
  if((pid = fork()) < 0)
    E_ErrnoFatalError("main", "could not fork child process");

  /* This is the child process */
  if(pid == 0)
  {
    fprintf(stderr, "Child process starting...\n");

    close(pipe1[1]);
    close(pipe2[0]);

    /* Connect stdin to pipe1 */
    if(pipe1[0] != 0)
    {
      dup2(pipe1[0], 0);
      close(pipe1[0]);
    }

    /* Connect stdout to pipe2 */
    if(pipe2[1] != 1)
    {
      dup2(pipe2[1], 1);
      close(pipe2[1]);
    }

    /* Exec the sfxserver program here */
    if(execlp(SFX_SERVER, SFX_SERVER, 0) < 0)
    {
      /* Send a quit signal to the parent */
      fprintf(stdout, "q");

      E_ErrnoFatalError("main", "child could not exec %s", SFX_SERVER);
    }
    /* It should never get here */
  }

  fprintf(stderr, "Parent process executing...\n");

  /* This must be the parent process */
  close(pipe1[0]);
  close(pipe2[1]);

  FD_ZERO(&read_fd);

  /* Now we need to wait for the ready signal from the server */
  for(;;)
  {
    FD_SET(pipe2[0], &read_fd);

    if(select(pipe2[0] + 1, &read_fd, NULL, NULL, NULL) < 0)
      E_ErrnoNonFatalError("main", "error in select() call");

    /* See if we need to read something from the child process */
    if(FD_ISSET(pipe2[0], &read_fd))
    {
      if((nread = read(pipe2[0], buffer, MAX_BUFFSIZE)) < 0)
	E_ErrnoNonFatalError("main", "error in child -> parent read()");

      /* If we got the ready signal, continue */
      if(!strncmp(buffer, READY, strlen(READY)))
	break;

      else
      {
	/* Add the null terminator so we can print it out */
	buffer[nread] = '\0';

	/* This prints out what was sent back by the server */
	fprintf(stderr, "%s", buffer);
      }
    }
  }

  fprintf(stderr, "Loading in sound files...\n");

  /* Now we can load in all of the sound effects */
  for(loop = 0; loop < MAX_SOUNDS; loop++)
  {
    sprintf(buffer, "l%s%d.snd", SOUND_DIR, loop);

    fprintf(stderr, "%s...", buffer);

    write(pipe1[1], buffer, strlen(buffer));
    write(pipe1[1], "\n", 1);

    /* Read in from the sfxserver */
    if((nread = read(pipe2[0], buffer, MAX_BUFFSIZE)) < 0)
      E_ErrnoNonFatalError("main", "error in reading doom sounds");

    fprintf(stderr, "done\n");
  }

  fprintf(stderr, "done\n");

  /* Now get ready for the interaction phase */
  FD_ZERO(&read_fd);

  for(;;)
  {
    FD_SET(pipe2[0], &read_fd);
    FD_SET(0, &read_fd);

    if(select(pipe2[0] + 1, &read_fd, NULL, NULL, NULL) < 0)
      E_ErrnoNonFatalError("main", "error in select() call");

    /* See if we need to read something from the child process */
    if(FD_ISSET(pipe2[0], &read_fd))
    {
      if((nread = read(pipe2[0], buffer, MAX_BUFFSIZE)) < 0)
	E_ErrnoNonFatalError("main", "error in child -> parent read()");

      if(buffer[0] == 'q')
      {
	fprintf(stderr, "Parent exiting on signal from child\n");
	break;
      }

      /* Add the null terminator so we can print it out */
      buffer[nread] = '\0';

      /* This prints out what was sent back by the server */
      fprintf(stderr, "%s", buffer);
    }

    /* See if we need to read something from the parent */
    if(FD_ISSET(0, &read_fd))
    {
      if((nread = read(0, buffer, MAX_BUFFSIZE)) < 0)
	E_ErrnoNonFatalError("main", "error in parent read()");

      write(pipe1[1], buffer, nread);
    }
  }

  close(pipe1[1]);
  close(pipe2[0]);
  exit(0);
}
