hal/external/marytts-5.1.2/doc/examples/client/c++/MaryClient.cc.win

291 lines
7.3 KiB
Text
Raw Normal View History

/**
* Copyright 2000-2006 DFKI GmbH.
* All Rights Reserved. Use is subject to license terms.
*
* Permission is hereby granted, free of charge, to use and distribute
* this software and its documentation without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of this work, and to
* permit persons to whom this work is furnished to do so, subject to
* the following conditions:
*
* 1. The code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* 2. Any modifications must be clearly marked as such.
* 3. Original authors' names are not deleted.
* 4. The authors' names are not used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* DFKI GMBH AND THE CONTRIBUTORS TO THIS WORK DISCLAIM ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DFKI GMBH NOR THE
* CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
* THIS SOFTWARE.
*/
#ifdef _WIN32
// use compiler option -L/<path to>/libwsock32.a
#include <winsock.h>
#else
#include <netdb.h>
#endif
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include "MaryClient.h"
using namespace std;
/**
* A C++ implementation of a simple client to the MARY TTS system.
* result: an empty string serving as the container for the output.
* It will return text or audio data; text data will be encoded as UTF-8.
* inputText: the UTF-8 encoded text (or XML document) to send as a request
* maryInFormat: the input type of the data in inputText, e.g. TEXT
* maryOutFormat: the output type to produce, e.g. MBROLA, AUDIO
* locale: the language of the input, e.g. EN-US, DE
* audioType: for AUDIO output, the type of audio data to produce,
* e.g. WAVE or MP3.
* voice: the voice to be used, e.g. cmu-slt-hsmm, bits3.
* effects: the list of effects to be generated.
* return value: 0 on success, negative on failure.
*/
int
MaryClient::maryQuery( int server_port,
string server_host,
string& result,
string inputText,
string maryInFormat,
string maryOutFormat,
string locale,
string audioType,
string voice,
string effects ) {
// prepare the request
string query = "MARY";
query += " IN=" + maryInFormat;
query += " OUT=" + maryOutFormat;
query += " LOCALE=" + locale; // remove this line, if using an older version than MARY 4.0
query += " AUDIO=" + audioType;
query += " VOICE=" + voice;
if (effects != "") {
query += " EFFECTS=" + effects;
}
query += "\012\015";
//cout << "Constructed query: " << query << endl;
// declare connection stuff
struct sockaddr_in maryServer;
struct sockaddr_in maryClient;
struct hostent* hostInfo;
// declare variables
int maryInfoSocket;
int maryDataSocket;
// set configuration parameters
// get host information
hostInfo = gethostbyname (server_host.c_str());
if (hostInfo == NULL)
{
return -2;
}
// create a tcp connection to the mary server
maryInfoSocket = socket (AF_INET, SOCK_STREAM, 0);
// verify that the socket could be opened successfully
if (maryInfoSocket == -1)
{
return -2;
}
else
// autoflush stdout, bind and connect
{
maryClient.sin_family = AF_INET;
maryClient.sin_port = htons (0);
maryClient.sin_addr.s_addr = INADDR_ANY;
int status = bind (maryInfoSocket, (struct sockaddr*) &maryClient, sizeof (maryClient));
if (status != 0)
{
return -2;
}
maryServer.sin_family = AF_INET;
maryServer.sin_port = htons (server_port);
memcpy ((char*) &maryServer.sin_addr.s_addr, hostInfo->h_addr_list [0], hostInfo->h_length);
status = connect (maryInfoSocket, (struct sockaddr*) &maryServer, sizeof (maryServer));
if (status != 0)
{
return -2;
}
}
// send request to the Mary server
if (send (maryInfoSocket, query.c_str (), query.size (), 0) == -1)
{
return -2;
}
// receive the request id
char id [32] = "";
if (recv (maryInfoSocket, id, 32, 0) == -1)
{
return -2;
}
//cout << "Read id: " << id << endl;
// create a tcp connection to the mary server
maryDataSocket = socket (AF_INET, SOCK_STREAM, 0);
// verify that the socket could be opened successfully
if (maryDataSocket == -1)
{
return -2;
}
else
// autoflush stdout, bind and connect
{
maryClient.sin_family = AF_INET;
maryClient.sin_port = htons (0);
maryClient.sin_addr.s_addr = INADDR_ANY;
int status = bind (maryDataSocket, (struct sockaddr*) &maryClient, sizeof (maryClient));
if (status != 0)
{
return -2;
}
maryServer.sin_family = AF_INET;
maryServer.sin_port = htons (server_port);
memcpy ((char*) &maryServer.sin_addr.s_addr, hostInfo->h_addr_list [0], hostInfo->h_length);
status = connect (maryDataSocket, (struct sockaddr*) &maryServer, sizeof (maryServer));
if (status != 0)
{
return -2;
}
}
// send the request id to the Mary server
if (send (maryDataSocket, id, strlen (id), 0) == -1)
{
return -2;
}
//cout << "Sending request: " << inputText << endl;
// send the query to the Mary server
if (send (maryDataSocket, inputText.c_str (), inputText.size (), 0) == -1)
{
return -2;
}
if (send (maryDataSocket, "\012\015", 2, 0) == -1)
{
return -2;
}
// shutdown data socket
shutdown (maryDataSocket, 1);
//cout << "Reading result" << endl;
unsigned int total_bytes = 0;
int recv_bytes = 0;
char data [1024] = "";
result [0] = '\0';
// receive the request result
do
{
data [0] = '\0';
recv_bytes = recv (maryDataSocket, data, 1024, 0);
if (recv_bytes == -1)
{
return -2;
}
else if (recv_bytes > 0)
{
//cout << "("<<recv_bytes<<")" << endl;
total_bytes += recv_bytes;
data [recv_bytes] = '\0';
if (maryOutFormat == "AUDIO")
{
for (unsigned int i=0; i<recv_bytes; i++)
{
result += data [i];
}
}
else
{
result += data;
}
}
} while (recv_bytes != 0);
if (result.size () != total_bytes)
{
cerr << "error: total bytes received != result bytes!" << endl;
cerr << " total bytes received = " << total_bytes << endl;
cerr << " result bytes = " << result.size () << endl;
}
// receive the request error
do
{
data [0] = '\0';
recv_bytes = recv (maryInfoSocket, data, 1024, 0);
if (recv_bytes == -1)
{
return -2;
}
else if (recv_bytes > 0)
{
cerr << endl << "Mary error code: " << data << endl;
return -3;
}
} while (recv_bytes != 0);
#ifdef _WIN32
// close all open sockets Windows
closesocket (maryInfoSocket);
closesocket (maryDataSocket);
#else
// close all open sockets UNIX
close (maryInfoSocket);
close (maryDataSocket);
#endif
return 0;
}