package sample.freetts;

/**
 * Copyright 2003 Sun Microsystems, Inc.
 * 
 * See the file "license.terms" for information on usage and
 * redistribution of this file, and for a DISCLAIMER OF ALL 
 * WARRANTIES.
 */
import java.io.File;
import java.util.Locale;
import java.util.Vector;

import javax.speech.Central;
import javax.speech.Engine;
import javax.speech.EngineList;
import javax.speech.synthesis.Synthesizer;
import javax.speech.synthesis.SynthesizerModeDesc;
import javax.speech.synthesis.SynthesizerProperties;
import javax.speech.synthesis.Voice;

/**
 * Simple program showing how to use FreeTTS using only the Java Speech API
 * (JSAPI).
 */
public class HelloWorld {

	/**
	 * Returns a "no synthesizer" message, and asks the user to check if the
	 * "speech.properties" file is at <code>user.home</code> or
	 * <code>java.home/lib</code>.
	 * 
	 * @return a no synthesizer message
	 */
	static private String noSynthesizerMessage() {
		String message = "No synthesizer created.  This may be the result of any\n"
				+ "number of problems.  It's typically due to a missing\n"
				+ "\"speech.properties\" file that should be at either of\n"
				+ "these locations: \n\n";
		message += "user.home    : " + System.getProperty("user.home") + "\n";
		message += "java.home/lib: "
				+ System.getProperty("java.home")
				+ File.separator
				+ "lib\n\n"
				+ "Another cause of this problem might be corrupt or missing\n"
				+ "voice jar files in the freetts lib directory.  This problem\n"
				+ "also sometimes arises when the freetts.jar file is corrupt\n"
				+ "or missing.  Sorry about that.  Please check for these\n"
				+ "various conditions and then try again.\n";
		return message;
	}

	/**
	 * Example of how to list all the known voices for a specific mode using
	 * just JSAPI. FreeTTS maps the domain name to the JSAPI mode name. The
	 * currently supported domains are "general," which means general purpose
	 * synthesis for tasks such as reading e-mail, and "time" which means a
	 * domain that's only good for speaking the time of day.
	 */
	public static void listAllVoices(String modeName) {

		System.out.println();
		System.out.println("All " + modeName
				+ " Mode JSAPI Synthesizers and Voices:");

		/*
		 * Create a template that tells JSAPI what kind of speech synthesizer we
		 * are interested in. In this case, we're just looking for a general
		 * domain synthesizer for US English.
		 */
		SynthesizerModeDesc required = new SynthesizerModeDesc(null, // engine
																		// name
				modeName, // mode name
				Locale.US, // locale
				null, // running
				null); // voices

		/*
		 * Contact the primary entry point for JSAPI, which is the Central
		 * class, to discover what synthesizers are available that match the
		 * template we defined above.
		 */
		EngineList engineList = Central.availableSynthesizers(required);
		for (int i = 0; i < engineList.size(); i++) {

			SynthesizerModeDesc desc = (SynthesizerModeDesc) engineList.get(i);
			System.out.println("    " + desc.getEngineName() + " (mode="
					+ desc.getModeName() + ", locale=" + desc.getLocale()
					+ "):");
			Voice[] voices = desc.getVoices();
			for (int j = 0; j < voices.length; j++) {
				System.out.println("        " + voices[j].getName());
			}
		}
	}

	public static void main(String[] args) {

		/*
		 * List all the "general" domain voices, which are voices that are
		 * capable of attempting to speak almost any text you throw at them.
		 */
		listAllVoices("general");

		String voiceName = (args.length > 0) ? args[0] : "kevin16";

		System.out.println();
		System.out.println("Using voice: " + voiceName);

		try {
			/*
			 * Find a synthesizer that has the general domain voice we are
			 * looking for. NOTE: this uses the Central class of JSAPI to find a
			 * Synthesizer. The Central class expects to find a
			 * speech.properties file in user.home or java.home/lib.
			 * 
			 * If your situation doesn't allow you to set up a speech.properties
			 * file, you can circumvent the Central class and do a very
			 * non-JSAPI thing by talking to FreeTTSEngineCentral directly. See
			 * the WebStartClock demo for an example of how to do this.
			 */
			SynthesizerModeDesc desc = new SynthesizerModeDesc(null, // engine
																		// name
					"general", // mode name
					Locale.US, // locale
					null, // running
					null); // voice
			Synthesizer synthesizer = Central.createSynthesizer(desc);

			/*
			 * Just an informational message to guide users that didn't set up
			 * their speech.properties file.
			 */
			if (synthesizer == null) {
				System.err.println(noSynthesizerMessage());
				System.exit(1);
			}

			/*
			 * Get the synthesizer ready to speak
			 */
			synthesizer.allocate();
			synthesizer.resume();

			/*
			 * Choose the voice.
			 */
			desc = (SynthesizerModeDesc) synthesizer.getEngineModeDesc();
			Voice[] voices = desc.getVoices();
			Voice voice = null;
			for (int i = 0; i < voices.length; i++) {
				if (voices[i].getName().equals(voiceName)) {
					voice = voices[i];
					break;
				}
			}
			if (voice == null) {
				System.err.println("Synthesizer does not have a voice named "
						+ voiceName + ".");
				System.exit(1);
			}
			synthesizer.getSynthesizerProperties().setVoice(voice);

			/*
			 * The the synthesizer to speak and wait for it to complete.
			 */
			synthesizer.speakPlainText("Hello world!", null);
			synthesizer.waitEngineState(Synthesizer.QUEUE_EMPTY);

			/*
			 * Clean up and leave.
			 */
			synthesizer.deallocate();
			System.exit(0);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
