import processing.core.*; 
import processing.xml.*; 

import java.awt.TextArea; 
import java.awt.Font; 
import java.awt.Color; 
import java.io.File; 
import ddf.minim.*; 
import java.io.IOException; 

import java.applet.*; 
import java.awt.Dimension; 
import java.awt.Frame; 
import java.awt.event.MouseEvent; 
import java.awt.event.KeyEvent; 
import java.awt.event.FocusEvent; 
import java.awt.Image; 
import java.io.*; 
import java.net.*; 
import java.text.*; 
import java.util.*; 
import java.util.zip.*; 
import java.util.regex.*; 

public class VoiceWriter extends PApplet {







TextArea ta;
AudioSnippet player;
Minim minim;

String currentWord;
String[] words;
String[] settings;


public void setup() {

  size(465, 370, JAVA2D);
  background(0, 0, 255);
  ta = new TextArea("", 15, 30, 1);
  ta.setFont(new java.awt.Font("Serif", Font.PLAIN, 20));
  ta.setForeground(Color.BLUE); 
  ta.addKeyListener(this);
  this.add(ta);


  minim = new Minim(this);
}

public void keyPressed(KeyEvent e) {

  if (e.getKeyCode() == 32 || e.getKeyCode() == KeyEvent.VK_ENTER) {
    speak();
  }
}

public void speak() {
  words = splitTokens(ta.getText());
  if (words.length > 0) {

    currentWord = words[words.length-1];
    File f = new File(sketchPath("recordings/"+currentWord+".wav"));
    if (f.exists()) {
      player = minim.loadSnippet("recordings/"+ f.getName());
      player.play();
    } 
    else{
      settings = loadStrings("data/voice.txt");
      TextToSpeech.say(currentWord, settings[0], PApplet.parseInt(settings[1]));
    }
  }
}

public void stop()
{
  player.close();
  minim.stop();
  super.stop();
}



static class TextToSpeech extends Object {

  // Store the voices, makes for nice auto-complete in Eclipse

  // male voices
  static final String ALEX = "Alex";
  static final String BRUCE = "Bruce";
  static final String FRED = "Fred";
  static final String JUNIOR = "Junior";
  static final String RALPH = "Ralph";

  // female voices
  static final String AGNES = "Agnes";
  static final String KATHY = "Kathy";
  static final String PRINCESS = "Princess";
  static final String VICKI = "Vicki";
  static final String VICTORIA = "Victoria";

  // novelty voices
  static final String ALBERT = "Albert";
  static final String BAD_NEWS = "Bad News";
  static final String BAHH = "Bahh";
  static final String BELLS = "Bells";
  static final String BOING = "Boing";
  static final String BUBBLES = "Bubbles";
  static final String CELLOS = "Cellos";
  static final String DERANGED = "Deranged";
  static final String GOOD_NEWS = "Good News";
  static final String HYSTERICAL = "Hysterical";
  static final String PIPE_ORGAN = "Pipe Organ";
  static final String TRINOIDS = "Trinoids";
  static final String WHISPER = "Whisper";
  static final String ZARVOX = "Zarvox";

  // throw them in an array so we can iterate over them / pick at random
  static String[] voices = {
    ALEX, BRUCE, FRED, JUNIOR, RALPH, AGNES, KATHY,
    PRINCESS, VICKI, VICTORIA, ALBERT, BAD_NEWS, BAHH,
    BELLS, BOING, BUBBLES, CELLOS, DERANGED, GOOD_NEWS,
    HYSTERICAL, PIPE_ORGAN, TRINOIDS, WHISPER, ZARVOX
  };

  // this sends the "say" command to the terminal with the appropriate args
  public static void say(String script, String voice, int speed) {
    try {
      Runtime.getRuntime().exec(new String[] {"say", "-v", voice, "[[rate " + speed + "]]" + script});
    }
    catch (IOException e) {
      System.err.println("IOException");
    }
  }

  // Overload the say method so we can call it with fewer arguments and basic defaults
  public static void say(String script) {
    // 200 seems like a resonable default speed
    say(script, ALEX, 200);
  }

}
  static public void main(String args[]) {
    PApplet.main(new String[] { "--bgcolor=#FFFFFF", "VoiceWriter" });
  }
}
