/*
  This file (c) Copyright 1998 - 2001 The MITRE Corporation
  
  This file is part of the Galaxy Communicator system. It is licensed
  under the conditions described in the file LICENSE in the root 
  directory of the Galaxy Communicator system.
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <strings.h>

#include "galaxy/util.h"
#define SERVER_FUNCTIONS_INCLUDE "testaudio_send_server.h"
#define USE_SERVER_DATA
#include "galaxy/server_functions.h"

#include "testaudio.h"

/*-----------------------------------------------------------------------*
 * Define statements for receiving audio from the MIT/MITRE audio server * 
 *-----------------------------------------------------------------------*/

#define AUDIO_SERVER_NEW_UTT "new_utt"
#define AUDIO_SERVER_SAMPLES_DONE "done"
#define AUDIO_SERVER_SAMPLES_ABORT "cancel"

static Gal_Frame prepare_audio_frame(GalIO_CommStruct *gcomm, char *filename)
{
  Gal_Frame f = Gal_MakeFrame("main", GAL_CLAUSE);
  FILE *fp;
  size_t count;
  int total;
  double *buf;
  GalIO_BrokerStruct *b;
  
  Gal_SetProp(f, ":sample_rate", Gal_IntObject(8000));

  GalUtil_PInfo1("read file %s\n", filename);
  if (!filename) {
    fprintf(stderr, "No filename provided\n");
    exit(1);
  }
  
  fp = fopen(filename, "r");
  if (!fp) {
    fprintf(stderr, "Couldn't open %s\n", filename);
    exit(1);
  }

  /* Now that we have the audio, we write the binary data
     through the broker. */
  
  b = GalIO_BrokerDataOutInit(gcomm, 0, 10);
  if (b && (GalIO_GetBrokerListenPort(b) > 0)) {
    GalIO_BrokerPopulateFrame(b, f, ":binary_host", ":binary_port");
    GalUtil_PInfo1("send utterance start\n");
    GalIO_BrokerWriteString(b, AUDIO_SERVER_NEW_UTT);

  /* If we're the sending direction, we read binary data from the file until
     we find EOF, and then we build a binary data structure. Once we do that,
     we transmit the data over a socket by transmitting the size
     of the memory buffer, and then transmitting the contents of the
     memory buffer. */

    buf = (double *) malloc(BLOCKSIZE * sizeof(double));
    count = fread(buf, sizeof(double), BLOCKSIZE, fp);
    total = count;
    GalUtil_PInfo1("reading file... %d %p\n", total, buf);
    while (count == BLOCKSIZE) {
      fprintf(stdout, "sending data %p\n", buf + total -count);
      fflush(stdout);
 
      GalIO_BrokerWriteInt16(b, &buf[total - count], count * 4);

      buf = (double *) realloc(buf, (total + BLOCKSIZE) * sizeof(double));
      count = fread(buf + total, sizeof(double), BLOCKSIZE, fp);    
      total += count;
      GalUtil_PInfo1("reading file... %d %p\n", total, buf);
    }
    //GalIO_BrokerWriteInt16(b, buf, total * 4);
    GalIO_BrokerWriteInt16(b, &buf[total - count], count * 4);
    fclose(fp);

    GalUtil_PInfo1("finish read file: %p %d\n", buf, total);

    GalUtil_PInfo1("send utterance end\n");

    GalIO_BrokerWriteString(b, AUDIO_SERVER_SAMPLES_DONE);
    GalIO_BrokerDataOutDone(b);
  }
  free(buf);
  return f;
}

Gal_Frame notify(Gal_Frame f, void *server_data)
{
  GalUtil_Print(-1, "Audio send: %s\n", Gal_GetString(f, ":notification"));
  return (Gal_Frame) NULL;
}

Gal_Frame reinitialize(Gal_Frame f, void *server_data)
{
  char *audiofile = Gal_GetString(f, ":audiofile");
  Gal_Frame fr;

  printf("Receive an reinitialize message!\n");
  if (audiofile) {
    /* Send a brokering message. */
    fr = prepare_audio_frame(GalSS_EnvComm((GalSS_Environment *) server_data),
			     audiofile);
    GalSS_EnvWriteFrame((GalSS_Environment *) server_data, fr, 0);
    Gal_FreeFrame(fr);
  }
  return (Gal_Frame) NULL;
}
