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
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
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
00073 int maryInfoSocket = socket(AF_INET, SOCK_STREAM, 0);
00074 if (maryInfoSocket == -1)
00075 return -2;
00076
00077
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
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
00100 char id [32] = "";
00101 if (recv(maryInfoSocket, id, 32, 0) == -1)
00102 return -2;
00103
00104
00105 int maryDataSocket = socket(AF_INET, SOCK_STREAM, 0);
00106 if (maryDataSocket == -1)
00107 return -2;
00108
00109
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
00126 if (send(maryDataSocket, id, strlen(id), 0) == -1)
00127 return -2;
00128
00129
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
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
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
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