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 #include <unistd.h>  // for fork, execlp, _exit, and close
00044 
00045 #include "MaryClient.h"
00046 
00047 void launchMaryServer() {
00048   pid_t child_id = fork();
00049   if ( child_id == 0 ) {
00050     char* tekrootval = getenv("TEKKOTSU_ROOT");
00051     std::string const tekkotsuRoot = tekrootval==NULL ? "/usr/local/Tekkotsu" : std::string(tekrootval);
00052     std::string const maryServerName = "tekk-maryserver";
00053     std::string const maryServerPath = tekkotsuRoot + "/tools/Mary/bin/" + maryServerName;
00054     execlp(maryServerPath.c_str(), maryServerName.c_str(), NULL);
00055     // If we get here, the execlp() failed
00056     std::cerr << "ERROR: failed to launch Mary server from " << maryServerPath << std::endl
00057         << "Check that TEKKOTSU_ROOT is set properly." << std::endl;
00058     _exit(0);
00059   }
00060 }
00061 
00062 int maryQuery(std::string& result,
00063         const std::string& inputText,
00064         const std::string& voice) {
00065 
00066   int server_port = 59125;
00067   int status;
00068 
00069   struct hostent* hostInfo = gethostbyname("localhost");
00070   if (hostInfo == NULL)
00071     return -2;
00072 
00073   // Create a tcp connection to the Mary server's info socket 
00074   int maryInfoSocket = socket(AF_INET, SOCK_STREAM, 0);
00075   if (maryInfoSocket == -1)
00076     return -2;
00077 
00078   // autoflush stdout, bind and connect
00079   struct sockaddr_in maryClient;
00080   maryClient.sin_family = AF_INET;
00081   maryClient.sin_port = htons(0);
00082   maryClient.sin_addr.s_addr = INADDR_ANY;
00083   status = bind(maryInfoSocket, (struct sockaddr*) &maryClient, sizeof(maryClient));
00084   if (status != 0)
00085     return -2;
00086 
00087   struct sockaddr_in maryServer;
00088   maryServer.sin_family = AF_INET;
00089   maryServer.sin_port = htons(server_port);
00090   memcpy((char*) &maryServer.sin_addr.s_addr, hostInfo->h_addr_list [0], hostInfo->h_length);
00091   status = connect(maryInfoSocket, (struct sockaddr*) &maryServer, sizeof(maryServer));
00092   if (status != 0)
00093     return -2;
00094 
00095   // prepare the request
00096   std::string const query = "MARY IN=TEXT_EN OUT=AUDIO AUDIO=WAVE VOICE=" + voice + "\012\015";
00097   if (send(maryInfoSocket, query.c_str(), query.size(), 0) == -1)
00098     return -2;
00099 
00100   // receive the request id
00101   char id [32] = "";
00102   if (recv(maryInfoSocket, id, 32, 0) == -1)
00103     return -2;
00104 
00105   // Create a tcp connection to the Mary server's data socket
00106   int maryDataSocket = socket(AF_INET, SOCK_STREAM, 0);
00107   if (maryDataSocket == -1)
00108     return -2;
00109 
00110   // autoflush stdout, bind and connect
00111   maryClient.sin_family = AF_INET;
00112   maryClient.sin_port = htons(0);
00113   maryClient.sin_addr.s_addr = INADDR_ANY;
00114 
00115   status = bind(maryDataSocket, (struct sockaddr*) &maryClient, sizeof(maryClient));
00116   if (status != 0)
00117     return -2;
00118 
00119   maryServer.sin_family = AF_INET;
00120   maryServer.sin_port = htons(server_port);
00121   memcpy((char*) &maryServer.sin_addr.s_addr, hostInfo->h_addr_list [0], hostInfo->h_length);
00122   status = connect(maryDataSocket, (struct sockaddr*) &maryServer, sizeof(maryServer));
00123   if (status != 0)
00124     return -2;
00125 
00126   // send the request id to the Mary server
00127   if (send(maryDataSocket, id, strlen(id), 0) == -1)
00128     return -2;
00129 
00130   // send the query to the Mary server
00131   if (send(maryDataSocket, inputText.c_str(), inputText.size(), 0) == -1)
00132     return -2;
00133   if (send(maryDataSocket, "\012\015", 2, 0) == -1)
00134     return -2;
00135   
00136   shutdown(maryDataSocket, 1);
00137 
00138   unsigned int total_bytes = 0;
00139   size_t recv_bytes = 0;
00140   char data [1024] = "";
00141   result[0] = '\0';
00142 
00143   // receive the request result
00144   do {
00145     data [0] = '\0';
00146     recv_bytes = recv(maryDataSocket, data, 1024, 0);
00147     if (recv_bytes == -1U)
00148       return -2;
00149     else if (recv_bytes > 0) {
00150       //std::cerr << "("<<recv_bytes<<")";
00151       total_bytes += recv_bytes;
00152       data [recv_bytes] = '\0';
00153 
00154       for (size_t i=0; i<recv_bytes; i++)
00155   result += data [i];
00156     }
00157   } while (recv_bytes != 0);
00158 
00159   if (result.size() != total_bytes) {
00160     std::cerr << "error: total bytes received != result bytes!" << std::endl;
00161     std::cerr << "       total bytes received = " << total_bytes << std::endl;
00162     std::cerr << "       result bytes = " << result.size() << std::endl;
00163   }
00164 
00165   // receive the request error
00166   do {
00167     data [0] = '\0';
00168     recv_bytes = recv(maryInfoSocket, data, 1024, 0);
00169     if (recv_bytes == -1U)
00170       return -2;
00171     else if (recv_bytes > 0) {
00172       std::cerr << std::endl << "Mary error code: " << data << std::endl;
00173       return -3;
00174     }
00175   } while (recv_bytes != 0);
00176 
00177   close(maryInfoSocket);
00178   close(maryDataSocket);
00179   return 0;
00180 }
00181 
00182 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:44 2016 by Doxygen 1.6.3