festival.c

00001 
00016 #define GITKR_SPEECH_FESTIVAL_C
00017 
00018 #include "gitkrincludes.h"
00019 
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <unistd.h>
00023 #include <string.h>
00024 #include <sys/types.h>
00025 #include <sys/socket.h>
00026 #include <netdb.h>
00027 #include <netinet/in.h>
00028 #include <arpa/inet.h>
00029 
00030 
00031 static gboolean festival_open(FT_Info *info) {
00032   return(((info->server_fd=festival_socket_open(info->server_host, info->server_port))!=-1));
00033 }
00034 
00041 FT_Info *festival_initialize(char *host, int port, char *mode) {
00042   FT_Info *info;
00043 
00044   info=calloc(1,sizeof(FT_Info));
00045 
00046   info->server_host=((host!=NULL)?host:FESTIVAL_DEFAULT_SERVER_HOST);
00047   info->server_port=((port!=-1  )?port:FESTIVAL_DEFAULT_SERVER_PORT);
00048   info->text_mode  =((mode!=NULL)?mode:FESTIVAL_DEFAULT_TEXT_MODE  );
00049 
00050   if(!festival_open(info)) {
00051     gitk_log("!! can't connect to festival speech service, try starting it");
00052     if(!system("festival >/tmp/festival.log --server &")) {
00053       sleep(1);
00054       if(!festival_open(info)) {
00055         gitk_log("!! can't connect to festival speech service, giving up");
00056         festival_done(info);return(NULL);
00057       }
00058     }
00059     else {
00060       gitk_log("!! can't start festival speech service");
00061       festival_done(info);return(NULL);
00062     }
00063   }
00064   
00065   return(info);
00066 }
00067 
00071 void festival_done(FT_Info *info) {
00072   if(!info) return;
00073 
00074   if(info->server_fd!=-1) close(info->server_fd);
00075 
00076   free(info);
00077 }
00078 
00093 void festival__say_text(FT_Info *info, const char *text) {
00094   FILE *fd;
00095   const char *p;
00096   char str[1024];
00097   guint sl;
00098 
00099   if(!info) return;
00100   if(info->server_fd == -1) return;
00101 
00102   gitk_log_intro();
00103   
00104   fd=fdopen(dup(info->server_fd),"wb");
00105 
00106   //-- copy text over to server, escaping any quotes
00107   fprintf(fd,"(SayText \"");
00108   for(p=text;(p && (*p!='\0'));p++) {
00109     //-- escape chars like '"' '\' with another '\' 
00110     if((*p=='"')||(*p=='\\')) putc('\\',fd);
00111     putc(*p,fd);
00112   }
00113   fputs("\")",fd);
00114   //fprintf(fd,"\" \"%s\")\n",info->text_mode);
00115   fclose(fd);
00116   
00117   fd=fdopen(dup(info->server_fd),"rb");
00118   
00119   while(TRUE) {
00120     // read response code
00121     fgets(str,1024,fd);
00122     sl=strlen(str);
00123     if(sl<3) break;
00124     // get last three chars (if there are at least three available
00125     p=&str[sl-3];
00126     if(!strncmp(p,"WV\n",3)) {
00127       gitk_log("festival response : waveform");
00128     }
00129     else if(!strncmp(p,"LP\n",3)) {
00130       gitk_log("festival response : expression");
00131       fgets(str,1024,fd);
00132       sl=strlen(str);
00133       if(sl>0) {
00134         str[sl-1]='\0';
00135         gitk_log1("  expression : \"%s\"",str);
00136       }
00137     }
00138     else if(!strncmp(p,"ER\n",3)) {
00139       gitk_log("festival response : error");
00140     }
00141     else if(!strncmp(p,"OK\n",3)) {
00142       gitk_log("festival response : okay");
00143       break;
00144     }
00145     else {
00146       gitk_log1("unknown festival response : \"%s\"",str);
00147     }
00148   }
00149   fclose(fd);
00150   gitk_log_outro();
00151 }
00152 
00153 //-- private helper
00154 
00156 static int festival_socket_open(const char *host, int port) {   
00157   struct sockaddr_in serv_addr;
00158   struct hostent *serverhost;
00159   int fd;
00160 
00161   fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00162 
00163   if (fd < 0) {
00164     gitk_log("festival_client: can't get socket");
00165     return -1;
00166   }
00167   memset(&serv_addr, 0, sizeof(serv_addr));
00168   if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
00169     /* its a name rather than an ipnum */
00170     serverhost = gethostbyname(host);
00171     if (serverhost == (struct hostent *)0) {
00172       gitk_log("festival_client: gethostbyname failed");
00173       return -1;
00174     }
00175     memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
00176   }
00177   serv_addr.sin_family = AF_INET;
00178   serv_addr.sin_port = htons(port);
00179 
00180   if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
00181     gitk_log("festival_client: connect to server failed");
00182     return -1;
00183   }
00184 
00185   return fd;
00186 }

Generated on Thu Oct 28 10:59:07 2004 for gitk by doxygen 1.3.6