MaryClient.cc
Go to the documentation of this file.00001 #if !defined(PLATFORM_APERIOS) && !defined(__APPLE__)
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
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>
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
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
00074 int maryInfoSocket = socket(AF_INET, SOCK_STREAM, 0);
00075 if (maryInfoSocket == -1)
00076 return -2;
00077
00078
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
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
00101 char id [32] = "";
00102 if (recv(maryInfoSocket, id, 32, 0) == -1)
00103 return -2;
00104
00105
00106 int maryDataSocket = socket(AF_INET, SOCK_STREAM, 0);
00107 if (maryDataSocket == -1)
00108 return -2;
00109
00110
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
00127 if (send(maryDataSocket, id, strlen(id), 0) == -1)
00128 return -2;
00129
00130
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
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
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
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