Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

MaryClient.cc

Go to the documentation of this file.
00001 #if !defined(PLATFORM_APERIOS) && !defined(__APPLE__)
00002 
00003 // Mary client code for Tekkotsu, modified from the Mary files
00004 // examples/client/c++/mary_client.cc and demo_mary_client.cc
00005 
00006 //**************** Original DFKI GmbH copyright notice:
00007 /**
00008  * Copyright 2000-2006 DFKI GmbH.
00009  * All Rights Reserved.  Use is subject to license terms.
00010  * 
00011  * Permission is hereby granted, free of charge, to use and distribute
00012  * this software and its documentation without restriction, including
00013  * without limitation the rights to use, copy, modify, merge, publish,
00014  * distribute, sublicense, and/or sell copies of this work, and to
00015  * permit persons to whom this work is furnished to do so, subject to
00016  * the following conditions:
00017  * 
00018  * 1. The code must retain the above copyright notice, this list of
00019  *    conditions and the following disclaimer.
00020  * 2. Any modifications must be clearly marked as such.
00021  * 3. Original authors' names are not deleted.
00022  * 4. The authors' names are not used to endorse or promote products
00023  *    derived from this software without specific prior written
00024  *    permission.
00025  *
00026  * DFKI GMBH AND THE CONTRIBUTORS TO THIS WORK DISCLAIM ALL WARRANTIES WITH
00027  * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
00028  * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DFKI GMBH NOR THE
00029  * CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
00030  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
00031  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
00032  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
00033  * THIS SOFTWARE.
00034  */
00035 
00036 #include <netinet/in.h>
00037 #include <sys/socket.h>
00038 #include <netdb.h>
00039 #include <cstdlib>
00040 #include <cstring>
00041 #include <string>
00042 #include <iostream>
00043 
00044 #include "MaryClient.h"
00045 
00046 void launchMaryServer() {
00047   pid_t child_id = fork();
00048   if ( child_id == 0 ) {
00049     char* tekrootval = getenv("TEKKOTSU_ROOT");
00050     std::string const tekkotsuRoot = tekrootval==NULL ? "/usr/local/Tekkotsu" : std::string(tekrootval);
00051     std::string const maryServerName = "tekk-maryserver";
00052     std::string const maryServerPath = tekkotsuRoot + "/tools/Mary/bin/" + maryServerName;
00053     execlp(maryServerPath.c_str(), maryServerName.c_str(), NULL);
00054     // If we get here, the execlp() failed
00055     std::cerr << "ERROR: failed to launch Mary server from " << maryServerPath << std::endl
00056         << "Check that TEKKOTSU_ROOT is set properly." << std::endl;
00057     _exit(0);
00058   }
00059 }
00060 
00061 int maryQuery(std::string& result,
00062         const std::string& inputText,
00063         const std::string& voice) {
00064 
00065   int server_port = 59125;
00066   int status;
00067 
00068   struct hostent* hostInfo = gethostbyname("localhost");
00069   if (hostInfo == NULL)
00070     return -2;
00071 
00072   // Create a tcp connection to the Mary server's info socket 
00073   int maryInfoSocket = socket(AF_INET, SOCK_STREAM, 0);
00074   if (maryInfoSocket == -1)
00075     return -2;
00076 
00077   // autoflush stdout, bind and connect
00078   struct sockaddr_in maryClient;
00079   maryClient.sin_family = AF_INET;
00080   maryClient.sin_port = htons(0);
00081   maryClient.sin_addr.s_addr = INADDR_ANY;
00082   status = bind(maryInfoSocket, (struct sockaddr*) &maryClient, sizeof(maryClient));
00083   if (status != 0)
00084     return -2;
00085 
00086   struct sockaddr_in maryServer;
00087   maryServer.sin_family = AF_INET;
00088   maryServer.sin_port = htons(server_port);
00089   memcpy((char*) &maryServer.sin_addr.s_addr, hostInfo->h_addr_list [0], hostInfo->h_length);
00090   status = connect(maryInfoSocket, (struct sockaddr*) &maryServer, sizeof(maryServer));
00091   if (status != 0)
00092     return -2;
00093 
00094   // prepare the request
00095   std::string const query = "MARY IN=TEXT_EN OUT=AUDIO AUDIO=WAVE VOICE=" + voice + "\012\015";
00096   if (send(maryInfoSocket, query.c_str(), query.size(), 0) == -1)
00097     return -2;
00098 
00099   // receive the request id
00100   char id [32] = "";
00101   if (recv(maryInfoSocket, id, 32, 0) == -1)
00102     return -2;
00103 
00104   // Create a tcp connection to the Mary server's data socket
00105   int maryDataSocket = socket(AF_INET, SOCK_STREAM, 0);
00106   if (maryDataSocket == -1)
00107     return -2;
00108 
00109   // autoflush stdout, bind and connect
00110   maryClient.sin_family = AF_INET;
00111   maryClient.sin_port = htons(0);
00112   maryClient.sin_addr.s_addr = INADDR_ANY;
00113 
00114   status = bind(maryDataSocket, (struct sockaddr*) &maryClient, sizeof(maryClient));
00115   if (status != 0)
00116     return -2;
00117 
00118   maryServer.sin_family = AF_INET;
00119   maryServer.sin_port = htons(server_port);
00120   memcpy((char*) &maryServer.sin_addr.s_addr, hostInfo->h_addr_list [0], hostInfo->h_length);
00121   status = connect(maryDataSocket, (struct sockaddr*) &maryServer, sizeof(maryServer));
00122   if (status != 0)
00123     return -2;
00124 
00125   // send the request id to the Mary server
00126   if (send(maryDataSocket, id, strlen(id), 0) == -1)
00127     return -2;
00128 
00129   // send the query to the Mary server
00130   if (send(maryDataSocket, inputText.c_str(), inputText.size(), 0) == -1)
00131     return -2;
00132   if (send(maryDataSocket, "\012\015", 2, 0) == -1)
00133     return -2;
00134   
00135   shutdown(maryDataSocket, 1);
00136 
00137   unsigned int total_bytes = 0;
00138   size_t recv_bytes = 0;
00139   char data [1024] = "";
00140   result[0] = '\0';
00141 
00142   // receive the request result
00143   do {
00144     data [0] = '\0';
00145     recv_bytes = recv(maryDataSocket, data, 1024, 0);
00146     if (recv_bytes == -1U)
00147       return -2;
00148     else if (recv_bytes > 0) {
00149       //std::cerr << "("<<recv_bytes<<")";
00150       total_bytes += recv_bytes;
00151       data [recv_bytes] = '\0';
00152 
00153       for (size_t i=0; i<recv_bytes; i++)
00154   result += data [i];
00155     }
00156   } while (recv_bytes != 0);
00157 
00158   if (result.size() != total_bytes) {
00159     std::cerr << "error: total bytes received != result bytes!" << std::endl;
00160     std::cerr << "       total bytes received = " << total_bytes << std::endl;
00161     std::cerr << "       result bytes = " << result.size() << std::endl;
00162   }
00163 
00164   // receive the request error
00165   do {
00166     data [0] = '\0';
00167     recv_bytes = recv(maryInfoSocket, data, 1024, 0);
00168     if (recv_bytes == -1U)
00169       return -2;
00170     else if (recv_bytes > 0) {
00171       std::cerr << std::endl << "Mary error code: " << data << std::endl;
00172       return -3;
00173     }
00174   } while (recv_bytes != 0);
00175 
00176   close(maryInfoSocket);
00177   close(maryDataSocket);
00178   return 0;
00179 }
00180 
00181 #endif

Tekkotsu v5.1CVS
Generated Fri Mar 16 05:26:44 2012 by Doxygen 1.6.3