1 /****************************************************************************
2 Main speaking functions for the FreeTTS Plug in
4 Copyright : (C) 2004 Paul Giannaros
6 Original author: Paul Giannaros <ceruleanblaze@gmail.com>
7 Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com>
8 ******************************************************************************/
10 /*******************************************************************************
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; version 2 of the License. *
16 ******************************************************************************/
18 #include <QtCore/QFileInfo>
22 #include <kconfiggroup.h>
23 #include <kstandarddirs.h>
24 #include <k3process.h>
26 #include "freettsproc.h"
29 FreeTTSProc::FreeTTSProc( QObject
* parent
, const QStringList
& /*args*/) :
30 PlugInProc( parent
, "freettsproc" ) {
31 kDebug() << "Running: FreeTTSProc::FreeTTSProc";
33 m_waitingStop
= false;
38 FreeTTSProc::~FreeTTSProc() {
39 kDebug() << "Running: FreeTTSProc::~FreeTTSProc";
46 /** Initializate the speech */
47 bool FreeTTSProc::init(KConfig
*config
, const QString
&configGroup
) {
48 kDebug() << "Running: FreeTTSProc::init()";
49 kDebug() << "Initializing plug in: FreeTTS";
50 KConfigGroup group
= config
->group(configGroup
);
51 m_freettsJarPath
= group
.readEntry("FreeTTSJarPath", "freetts.jar");
52 kDebug() << "FreeTTSProc::init: path to freetts.jar: " << m_freettsJarPath
;
57 * Say a text. Synthesize and audibilize it.
58 * @param text The text to be spoken.
60 * If the plugin supports asynchronous operation, it should return immediately.
62 void FreeTTSProc::sayText(const QString
&text
) {
63 synth(text
, QString(), m_freettsJarPath
);
67 * Synthesize text into an audio file, but do not send to the audio device.
68 * @param text The text to be synthesized.
69 * @param suggestedFilename Full pathname of file to create. The plugin
70 * may ignore this parameter and choose its own
71 * filename. KTTSD will query the generated
72 * filename using getFilename().
74 * If the plugin supports asynchronous operation, it should return immediately.
76 void FreeTTSProc::synthText(const QString
& text
, const QString
& suggestedFilename
) {
77 kDebug() << "Running: FreeTTSProc::synthText";
78 synth(text
, suggestedFilename
, m_freettsJarPath
);
81 void FreeTTSProc::synth(
83 const QString
&synthFilename
,
84 const QString
& freettsJarPath
) {
86 kDebug() << "Running: FreeTTSProc::synth";
89 if (m_freettsProc
->isRunning()) m_freettsProc
->kill();
94 m_freettsProc
= new K3Process
;
95 connect(m_freettsProc
, SIGNAL(processExited(K3Process
*)),
96 this, SLOT(slotProcessExited(K3Process
*)));
97 connect(m_freettsProc
, SIGNAL(receivedStdout(K3Process
*, char*, int)),
98 this, SLOT(slotReceivedStdout(K3Process
*, char*, int)));
99 connect(m_freettsProc
, SIGNAL(receivedStderr(K3Process
*, char*, int)),
100 this, SLOT(slotReceivedStderr(K3Process
*, char*, int)));
101 connect(m_freettsProc
, SIGNAL(wroteStdin(K3Process
*)),
102 this, SLOT(slotWroteStdin(K3Process
* )));
103 if (synthFilename
.isNull())
106 m_state
= psSynthing
;
109 QString saidText
= text
;
112 /// As freetts.jar doesn't seem to like being called from an absolute path,
113 /// we need to strip off the path to freetts.jar and pass it to
114 /// K3Process::setWorkingDirectory()
115 /// We could just strip off 11 characters from the end of the path to freetts.jar, but thats
116 /// not exactly very portable...
117 QString filename
= QFileInfo(freettsJarPath
).baseName().append(QString(".").append(QFileInfo(freettsJarPath
).suffix()));
118 QString freettsJarDir
= freettsJarPath
.left((freettsJarPath
.length() - filename
.length()) - 1);
120 m_freettsProc
->setWorkingDirectory(freettsJarDir
);
121 kDebug() << "FreeTTSProc::synthText: moved to directory '" << freettsJarDir
<< "'";
122 kDebug() << "FreeTTSProc::synthText: Running file: '" << filename
<< "'";
123 *m_freettsProc
<< "java" << "-jar" << filename
;
125 /// Dump audio into synthFilename
127 if (!synthFilename
.isNull()) *m_freettsProc
<< "-dumpAudio" << synthFilename
;
129 m_synthFilename
= synthFilename
;
131 kDebug() << "FreeTTSProc::synth: Synthing text: '" << saidText
<< "' using FreeTTS plug in";
132 if (!m_freettsProc
->start(K3Process::NotifyOnExit
, K3Process::All
)) {
133 kDebug() << "FreeTTSProc::synth: Error starting FreeTTS process. Is freetts.jar in the PATH?";
135 kDebug() << "K3Process args: " << m_freettsProc
->args();
138 kDebug()<< "FreeTTSProc:synth: FreeTTS initialized";
139 m_freettsProc
->writeStdin(saidText
.toLatin1(), saidText
.length());
143 * Returning the filename of the synth'd text
144 * @returns The filename of the last synth'd text
146 QString
FreeTTSProc::getFilename() {
147 kDebug() << "FreeTTSProc::getFilename: returning " << m_synthFilename
;
148 return m_synthFilename
;
152 * Stop current operation (saying or synthesizing text).
153 * Important: This function may be called from a thread different from the
154 * one that called sayText or synthText.
155 * If the plugin cannot stop an in-progress @ref sayText or
156 * @ref synthText operation, it must not block waiting for it to complete.
157 * Instead, return immediately.
159 * If a plugin returns before the operation has actually been stopped,
160 * the plugin must emit the @ref stopped signal when the operation has
163 * The plugin should change to the psIdle state after stopping the
166 void FreeTTSProc::stopText() {
167 kDebug() << "FreeTTSProc::stopText:: Running";
169 if (m_freettsProc
->isRunning()) {
170 kDebug() << "FreeTTSProc::stopText: killing FreeTTS.";
171 m_waitingStop
= true;
172 m_freettsProc
->kill();
174 else m_state
= psIdle
;
176 else m_state
= psIdle
;
177 kDebug() << "FreeTTSProc::stopText: FreeTTS stopped.";
180 void FreeTTSProc::slotProcessExited(K3Process
*) {
181 kDebug() << "FreeTTSProc:slotProcessExited: FreeTTS process has exited.";
182 pluginState prevState
= m_state
;
184 m_waitingStop
= false;
189 m_state
= psFinished
;
190 if (prevState
== psSaying
)
192 else if (prevState
== psSynthing
)
193 emit
synthFinished();
197 void FreeTTSProc::slotReceivedStdout(K3Process
*, char* buffer
, int buflen
) {
198 QString buf
= QString::fromLatin1(buffer
, buflen
);
199 kDebug() << "FreeTTSProc::slotReceivedStdout: Received output from FreeTTS: " << buf
;
202 void FreeTTSProc::slotReceivedStderr(K3Process
*, char* buffer
, int buflen
) {
203 QString buf
= QString::fromLatin1(buffer
, buflen
);
204 kDebug() << "FreeTTSProc::slotReceivedStderr: Received error from FreeTTS: " << buf
;
207 void FreeTTSProc::slotWroteStdin(K3Process
*) {
208 kDebug() << "FreeTTSProc::slotWroteStdin: closing Stdin";
209 m_freettsProc
->closeStdin();
213 * Return the current state of the plugin.
214 * This function only makes sense in asynchronous mode.
215 * @return The pluginState of the plugin.
219 pluginState
FreeTTSProc::getState() {
224 * Acknowledges a finished state and resets the plugin state to psIdle.
226 * If the plugin is not in state psFinished, nothing happens.
227 * The plugin may use this call to do any post-processing cleanup,
228 * for example, blanking the stored filename (but do not delete the file).
229 * Calling program should call getFilename prior to ackFinished.
231 void FreeTTSProc::ackFinished() {
232 if (m_state
== psFinished
) {
234 m_synthFilename
.clear();
239 * Returns True if the plugin supports asynchronous processing,
240 * i.e., returns immediately from sayText or synthText.
241 * @return True if this plugin supports asynchronous processing.
243 * If the plugin returns True, it must also implement @ref getState .
244 * It must also emit @ref sayFinished or @ref synthFinished signals when
245 * saying or synthesis is completed.
247 bool FreeTTSProc::supportsAsync() {
253 * Returns True if the plugIn supports synthText method,
254 * i.e., is able to synthesize text to a sound file without
255 * audibilizing the text.
256 * @return True if this plugin supports synthText method.
258 bool FreeTTSProc::supportsSynth() {
264 #include "freettsproc.moc"