/* program to speak multiple lines of text
        lines read from standard in
           each line may be up to 1000 characters in length
           including terminating null
        speech comes from espeak program
        program halts when line "eSpeakABBCCCDDDEEEEFFFFdone" read
*/

/* compile with the command:
   gcc -lespeak -o textlines-to-speech textlines-to-speech.c

 */

#include <stdio.h>
#include <string.h>
#include <espeak/speak_lib.h>
#include <semaphore.h>       /* semaphores for text-to-speech synchronization */
#include <fcntl.h>           /* for semaphore constants */
#include <errno.h>

int MAX = 1000;   // maximum characters in an input line

sem_t *sem_done;  // semaphore for synchronization is eSpeackPackage.c

/* libraries for the random number generator */
#include <stdlib.h>
#include <time.h>

/* read next [non-empty] line from input 
   empty lines will be skipped 
   initial whitespace is ignored
   full line array is initialized (nulls placed at end)
*/
void read_line (char * line)
{
       /* get next [non-empty] line */
       /* initial whitespace is trimmed */
        printf ("a\n");
        char ch = getchar();
       printf ("b\n");
       while (isspace(ch))
         {
           if (ch == '\n')
             /* if at end of line, signal for next line */
             sem_post (sem_done);
           ch = fgetc(stdin);
         }
       printf ("non-white-space found\n");
       line[0] = ch;

       /* read line until '\n' */
       int i = 1;
       while ((i < MAX-1) && ((line[i] = fgetc(stdin)) != '\n'))
         i++;
       /* null character throughout rest of input line */
       for (; i < MAX; i++)
         line[i] = 0;

       /*  // get next line
      for (i = 0; i < MAX; i++)  // first, null entire line array
        line[i] = 0;
      fgets (line, MAX, stdin);
      // remove newline character, if present
      if (line[strlen(line)-1] == '\n')
      line[strlen(line)-1] = 0;     */
}

int main ()
{
  char line[MAX];

  /* sentinel strings for processing commands */
  char * terminating_string = "eSpeakABBCCCDDDEEEEFFFFdone";
  char * set_voice_female = "eSpeakABBCCCDDDEEEEFFFFfemale";
  char * set_voice_male = "eSpeakABBCCCDDDEEEEFFFFmale";

 /* initalize eSpeak package */
  espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, NULL, 0);
  espeak_SetVoiceByName("en-us");
  espeak_SetParameter(espeakRATE, 140, 0);

  
  /* set voice randomly to female or male */
  srand (time ((time_t *) 0) ); // initialize random generator

  int i, rand_num;
  for (i = 0; i < 10; i++)
    rand_num = rand() % 10;
  /* printf ("rand_num = %d\n", rand_num);*/
  if (rand_num < 5)
    {
      espeak_VOICE his_voice = {NULL, NULL, NULL, 1, 55, 0, 0, 0};
      espeak_SetVoiceByProperties(&his_voice);
     printf ("initialization male\n");

          // speak line
      espeak_Synth("initialized with male voice", strlen("initialized with male voice"), 0, POS_CHARACTER, 0, 0,
                       NULL, NULL);
      // wait for speaking to finish
      espeak_Synchronize();  
    }   
  else
    {
      espeak_VOICE her_voice = {NULL, NULL, NULL, 2, 32, 0, 0, 0};
      espeak_SetVoiceByProperties(&her_voice);
      printf ("initialization female\n");
      espeak_Synth("initialized with female voice", strlen("initialized with female voice"), 0, POS_CHARACTER, 0, 0,
                   NULL, NULL);
      // wait for speaking to finish
      espeak_Synchronize();  

    }

  /* setup named semaphore for synchronization with eSpeakPackage.c */
   /* set up read, continue semaphore for synchronization with
      textlines-to-speech.c
   */
   int hostnameMAX = 50;
   char hostname [hostnameMAX];
   gethostname (hostname, hostnameMAX);
   
   char sem_done_name [hostnameMAX];
   strcpy (sem_done_name, "/espeak-sem-done-");
   strcat (sem_done_name, hostname);
   printf ("semaphorename: %s \n", sem_done_name); 

   /* set up named semaphones with permissions 0644
      both semaphores initialized to value 0
   */
   sem_done  = sem_open(sem_done_name,  O_CREAT, 0666, 0); 
   if (sem_done == SEM_FAILED)
     printf ("error opening sem done\n");

   printf ("semaphores in textlines-to-speech initialized\n");
   /* signal eSpeakPackage that setup done */
   if (sem_post (sem_done) == 0)
     printf ("sem_post incremented\n");
   else
     printf ("sem_post increment failed\n");
   
  int sem_value;
  sem_getvalue (sem_done, &sem_value);
  printf ("value of sentinel - 1:  %d\n", sem_value);

  printf ("on to first read in textlines-to-speech\n");

  /* retrieve first line */
  read_line (line);

  sem_getvalue (sem_done, &sem_value);
  printf ("value of sentinel - 2:  %d\n", sem_value);

  printf ("Line before main loop:  '%s'\n", line);

  while (strcmp (line, terminating_string) != 0)
    { 
  sem_getvalue (sem_done, &sem_value);
  printf ("value of sentinel:  %d\n", sem_value);
      printf ("Line:  '%s'\n", line);
      // check voice parameter commands 


      /*
      if (strcmp(line, set_voice_female) == 0)
        {
          espeak_VOICE her_voice = {NULL, NULL, NULL, 2, 0, 0, 0, 0};
          espeak_SetVoiceByProperties(&her_voice);
          printf ("change female\n");
        }
      else if (strcmp(line, set_voice_male) == 0)
        {
          espeak_VOICE his_voice = {NULL, NULL, NULL, 1, 0, 0, 0, 0};
          espeak_SetVoiceByProperties(&his_voice);
          printf ("change male\n");
        }
      else
        {
          if (strlen(line) > 0)
            {
      */
              // speak line
              espeak_Synth(line, strlen(line), 0, POS_CHARACTER, 0, 0, NULL, NULL);
              // wait for speaking to finish
              espeak_Synchronize();  
              /*
            }
        }
              */
       sem_post (sem_done);

       read_line (line);

      printf ("string length:  %dn", strlen(line)); 
    }

  sem_getvalue (sem_done, &sem_value);
  printf ("value of sentinel:  %d\n", sem_value);

  /* clean up semaphores */
  sem_close (sem_done);

  char full_sem_done_name [50];
  strcpy ( full_sem_done_name, "/run/shm/sem.espeak-sem-done-curry");
 if (remove (full_sem_done_name))
   printf ("error in removing semaphore %s; code %s\n", full_sem_done_name, strerror(errno));

  return 0;
}
