package org.myrobotlab.service;
import java.util.HashMap;
import org.myrobotlab.framework.Service;
import org.myrobotlab.framework.ServiceType;
import org.myrobotlab.logging.Level;
import org.myrobotlab.logging.Logging;
import org.myrobotlab.logging.LoggingFactory;
import org.myrobotlab.service.interfaces.SpeechRecognizer;
import org.myrobotlab.service.interfaces.SpeechSynthesis;
import org.myrobotlab.service.interfaces.TextListener;
import org.myrobotlab.service.interfaces.TextPublisher;
/**
*
* WebkitSpeechRecognition - uses the speech recognition that is built into the
* chrome web browser this service requires the webgui to be running.
*
*/
public class WebkitSpeechRecognition extends Service implements SpeechRecognizer, TextPublisher {
/**
* TODO: make it's own class. TODO: merge this data structure with the
* programab oob stuff?
*
*/
public class Command {
public String name;
public String method;
public Object[] params;
Command(String name, String method, Object[] params) {
this.name = name;
this.method = method;
this.params = params;
}
}
/**
*
*/
private static final long serialVersionUID = 1L;
private String language = "en-US";
HashMap<String, Command> commands = new HashMap<String, Command>();
// track the state of the webgui, is it listening? maybe?
public boolean listening = false;
public WebkitSpeechRecognition(String reservedKey) {
super(reservedKey);
}
@Override
public String publishText(String text) {
log.info("Publish Text : {}", text);
// TODO: is there a better place to do this? maybe recognized?
// TODO: remove this! it probably should be invoking the command on publish
// text.. only on recognized?!
// not sure.
String cleantext = text.toLowerCase().trim();
/*
* Double Speak FIX - I don't think a cmd should be sent from here because
* it's not 'recognized' - recognized sends commands this method should be
* subscribed too - GroG
*
* if (commands.containsKey(cleantext)) { // If we have a command. send it
* when we recognize... Command cmd = commands.get(cleantext);
* send(cmd.name, cmd.method, cmd.params); }
*/
return cleantext;
}
@Override
public void listeningEvent() {
// TODO Auto-generated method stub
}
@Override
public void pauseListening() {
// TODO Auto-generated method stub
}
@Override
public String recognized(String text) {
log.info("Recognized : >{}<", text);
String cleanedText = text.toLowerCase().trim();
if (commands.containsKey(cleanedText)) {
// If we have a command. send it when we recognize...
Command cmd = commands.get(cleanedText);
send(cmd.name, cmd.method, cmd.params);
}
return cleanedText;
}
@Override
public void resumeListening() {
log.info("Resume listening event seen.");
this.listening = true;
broadcastState();
}
@Override
public void startListening() {
log.info("Start listening event seen.");
this.listening = true;
broadcastState();
}
@Override
public void stopListening() {
log.info("Stop listening event seen.");
this.listening = false;
broadcastState();
}
public void setLanguage(String language) {
// Here we want to set the language string and broadcast the update to the
// web gui so that it knows to update the language on webkit speech
this.language = language;
broadcastState();
}
public String getLanguage() {
// a getter for it .. just in case.
return this.language;
}
@Override
public void addTextListener(TextListener service) {
addListener("publishText", service.getName(), "onText");
}
@Override
public void addMouth(SpeechSynthesis mouth) {
mouth.addEar(this);
// TODO : we can implement the "did you say x?"
// logic like sphinx if we want here.
// when we add the ear, we need to listen for request confirmation
}
@Override
public void onStartSpeaking(String utterance) {
// at this point we should subscribe to this in the webgui
// so we can pause listening.
}
@Override
public void onEndSpeaking(String utterance) {
// need to subscribe to this in the webgui
// so we can resume listening.
}
public static void main(String[] args) {
LoggingFactory.init(Level.INFO);
try {
Runtime.start("webgui", "WebGui");
Runtime.start("webkitspeechrecognition", "WebkitSpeechRecognition");
} catch (Exception e) {
Logging.logError(e);
}
}
/**
* This static method returns all the details of the class without it having
* to be constructed. It has description, categories, dependencies, and peer
* definitions.
*
* @return ServiceType - returns all the data
*
*/
static public ServiceType getMetaData() {
ServiceType meta = new ServiceType(WebkitSpeechRecognition.class.getCanonicalName());
meta.addDescription("Speech recognition using Google Chrome webkit");
meta.addCategory("speech recognition");
// meta.addPeer("tracker", "Tracking", "test tracking");
return meta;
}
@Override
public void lockOutAllGrammarExcept(String lockPhrase) {
log.warn("Lock out grammar not supported on webkit, yet...");
}
@Override
public void clearLock() {
log.warn("clear lock out grammar not supported on webkit, yet...");
}
// TODO - should this be in Service ?????
public void addCommand(String actionPhrase, String name, String method, Object... params) {
actionPhrase = actionPhrase.toLowerCase().trim();
if (commands == null) {
commands = new HashMap<String, Command>();
}
commands.put(actionPhrase, new Command(name, method, params));
}
// TODO: this might need to go into the interface if we want to support it.
public void addComfirmations(String... txt) {
log.warn("Confirmation support not enabled in webkit speech.");
}
// TODO: this might need to go into the interface if we want to support it.
public void addNegations(String... txt) {
log.warn("Negations not enabled in webkit speech.");
}
public void startListening(String grammar) {
log.warn("Webkit speech doesn't listen for a specific grammar. use startListening() instead. ");
startListening();
}
}