Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/metaobjects/misc/festtalk.cc

Go to the documentation of this file.
00001 /* $Id: festtalk.cc,v 1.27 2003/07/23 00:17:26 reed Exp $ */
00002 
00003 
00004 /** @file festtalk.cc
00005     Defines FestTalk a subclass of Talkative that sends messages to a Festival speech synthesis server.
00006 
00007     I am a moron. I deleted this file, and now I have to rewrite it.
00008     @author Reed Hedges <reed@zerohour.net> December, 2001
00009     Portions of this code were developed at the University of Massachusetts.
00010 */
00011 
00012 
00013 /* an idea for future improvement: be a listener to the voice property directly, and only set the voice (with festival_eval_command) when it changes. */
00014 
00015 
00016 #include <sys/types.h>
00017 #include <unistd.h>
00018 #include <errno.h>
00019 
00020 #include <vos/corelibs/vos/vos.hh>
00021 
00022 #include "festtalk.hh"
00023 
00024 
00025 // Initialize static class members:
00026 char* FestTalk::festival_host = "127.0.0.1";
00027 int FestTalk::festival_port = 1314;
00028 
00029 
00030 
00031 void FestTalk::set_server(char *host, int port) {
00032     festival_host = host;
00033     festival_port = port;
00034 }
00035 
00036 
00037 void FestTalk::festival_server_command(const char *cmd) throw (ServerCommError) {
00038     if(strcmp(cmd, VOS_TALK_NO_VOICE) != 0) {
00039         if( fprintf(socket_fp, "%s\n", cmd) <= 0)
00040             throw ServerCommError("Error writing command.");
00041         fflush(socket_fp);
00042     }
00043 }
00044 
00045 /* replaces substrings.  */
00046 string sreplace( const string& s, const string& key, const string& value) {
00047     string tmp(s);
00048     unsigned int k;
00049     while( (k = tmp.find(key)) != tmp.npos )
00050         tmp = tmp.replace( k, key.length(), value);
00051     return tmp;
00052 }
00053 void FestTalk::festival_server_saytext(const string& text) throw (ServerCommError) {
00054 
00055     string::size_type f = 0;
00056     string::size_type pos = 0;
00057 
00058 
00059     // divide text up in phrases?
00060     // XXX TODO: broken -- see apps/tour/tourguide.cc for more complete
00061     if(phrase_delim != NULL) {
00062         while( (f = text.find_first_of(phrase_delim, pos)) != text.npos) {
00063             if( fprintf(socket_fp, "(SayText \"%s\")", text.substr(pos, f).c_str()) <= 0)
00064                 throw ServerCommError("Error writing command.");
00065             pos = f;
00066         }
00067     } else {
00068         if( fprintf(socket_fp, "(SayText \"%s\")\n", text.c_str()) <= 0 )
00069             throw ServerCommError("Error writing command.");
00070     }
00071     fflush(socket_fp);
00072 }
00073 
00074 
00075 void FestTalk::open_server(char *host, int port) throw (ServerCommError) {
00076     struct sockaddr_in address;
00077     LOG("Festival Talkative", 3, "Opening connection to Festival server at " << host << ":" << port);
00078     if( (socket_fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
00079         LOG("Festival Talkative", 0, "Error creating socket. " << strerror(errno));
00080         throw ServerCommError(string("Error opening server: ") + strerror(errno));
00081         return;
00082     }
00083     struct hostent* he;
00084     if(!(he = gethostbyname(host))) {
00085         LOG("Festival Talkative", 0, "Error: Invalid address. " << host);
00086         throw ServerCommError("Invalid address.");
00087         return;
00088     }
00089     memset(&address, 0, sizeof(address));
00090     address.sin_port=htons(port);
00091     address.sin_family=AF_INET;
00092     address.sin_addr=*((struct in_addr *)he->h_addr);
00093     if( connect(socket_fd, (struct sockaddr *)&address, sizeof(address)) == -1) {
00094         LOG("Festival Talkative", 0, "Error connecting to server " << host << ":" << port << ". " << strerror(errno));
00095         throw ServerCommError(string("Error connecting to server: ") + strerror(errno));
00096         return;
00097     }
00098 
00099     if(! (socket_fp = fdopen(socket_fd, "r+")) ) {
00100         LOG("Festival Talkative", 0, "Error opening stream from fd.");
00101         throw ServerCommError("Error opening stream fp from socket file descriptor!!");
00102 
00103         return;
00104     }
00105 }
00106 
00107 
00108 
00109 void FestTalk::close_server() {
00110     fclose(socket_fp);
00111     if ( shutdown(socket_fd, 2) < 0 ) {
00112         LOG("Festival Talkative", 0, "Warning: Error closing socket. " << strerror(errno));
00113     }
00114 }
00115 
00116 
00117 /** Constructor: opens socket to Festival server */
00118 FestTalk::FestTalk(MetaObject *super)  throw (ServerCommError)
00119     : LocalTalkative(super), Talkative(super), MetaObject(super) {
00120     phrase_delim = NULL;
00121     try {
00122         open_server(festival_host, festival_port);
00123     } catch (ServerCommError e) {
00124         throw e;
00125     }
00126 //  open_server("127.0.0.1", 1314);
00127 }
00128 
00129 /** Destructor: closes connection to festival server */
00130 FestTalk::~FestTalk() {
00131     close_server();
00132 
00133 }
00134 
00135 
00136 /** Say message actuator. */
00137 void FestTalk::do_say(TalkMessage& m) throw (ServerCommError) {
00138     LOG("Festival Talkative", 3, "Speaking message...");
00139     try {
00140         festival_server_command(m.sender.get_voice().c_str());
00141         festival_server_saytext(m.text);
00142     } catch (ServerCommError e) {
00143         throw e;
00144     }
00145     LOG("Festival Talkative", 3, "Done speaking.");
00146 }
00147 
00148 void FestTalk::registerExtenders() {
00149     LocalSite::addLocalObjectExtension(typeid(FestTalk).name(), new_FestTalk);
00150     RemoteSite::addRemoteObjectExtension(typeid(FestTalk).name(), new_FestTalk);
00151 }
00152 
00153 /** Static generator, for factory. */
00154 MetaObject* FestTalk::new_FestTalk(MetaObject* superobject, const string& type) {
00155     return new FestTalk(superobject);
00156 }
00157 
00158 

Generated on Tue Aug 12 03:55:44 2003 for Interreality Project - VOS by doxygen 1.3.2