Remove this line
[kdeaccessibility.git] / kttsd / plugins / flite / fliteproc.cpp
blobd8822d5f3cdc6fb627b35b729fe37d08457127db
1 /***************************************************** vim:set ts=4 sw=4 sts=4:
2 Main speaking functions for the Festival Lite (Flite) Plug in
3 -------------------
4 Copyright:
5 (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
6 -------------------
7 Original author: Gary Cramblitt <garycramblitt@comcast.net>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 ******************************************************************************/
24 // Flite Plugin includes.
25 #include "fliteproc.h"
26 #include "fliteproc.moc"
28 // Qt includes.
31 // KDE includes.
32 #include <kdebug.h>
33 #include <kconfig.h>
34 #include <kconfiggroup.h>
35 #include <kstandarddirs.h>
36 #include <k3process.h>
38 /** Constructor */
39 FliteProc::FliteProc( QObject* parent, const QStringList& ) :
40 PlugInProc( parent, "fliteproc" ){
41 kDebug() << "FliteProc::FliteProc: Running";
42 m_state = psIdle;
43 m_waitingStop = false;
44 m_fliteProc = 0;
47 /** Destructor */
48 FliteProc::~FliteProc(){
49 kDebug() << "FliteProc::~FliteProc:: Running";
50 if (m_fliteProc)
52 stopText();
53 delete m_fliteProc;
57 /** Initialize the speech */
58 bool FliteProc::init(KConfig* c, const QString& configGroup){
59 // kDebug() << "Running: FliteProc::init(const QString &lang)";
60 // kDebug() << "Initializing plug in: Flite";
61 // Retrieve path to flite executable.
62 KConfigGroup config(c, configGroup);
63 m_fliteExePath = config.readEntry("FliteExePath", "flite");
64 kDebug() << "FliteProc::init: path to flite: " << m_fliteExePath;
65 return true;
68 /**
69 * Say a text. Synthesize and audibilize it.
70 * @param text The text to be spoken.
72 * If the plugin supports asynchronous operation, it should return immediately.
74 void FliteProc::sayText(const QString &text)
76 synth(text, QString(), m_fliteExePath);
79 /**
80 * Synthesize text into an audio file, but do not send to the audio device.
81 * @param text The text to be synthesized.
82 * @param suggestedFilename Full pathname of file to create. The plugin
83 * may ignore this parameter and choose its own
84 * filename. KTTSD will query the generated
85 * filename using getFilename().
87 * If the plugin supports asynchronous operation, it should return immediately.
89 void FliteProc::synthText(const QString& text, const QString& suggestedFilename)
91 synth(text, suggestedFilename, m_fliteExePath);
94 /**
95 * Say or Synthesize text.
96 * @param text The text to be synthesized.
97 * @param suggestedFilename If not Null, synthesize only to this filename, otherwise
98 * synthesize and audibilize the text.
100 void FliteProc::synth(
101 const QString &text,
102 const QString &synthFilename,
103 const QString& fliteExePath)
105 // kDebug() << "Running: FliteProc::synth(const QString &text)";
107 if (m_fliteProc)
109 if (m_fliteProc->isRunning()) m_fliteProc->kill();
110 delete m_fliteProc;
111 m_fliteProc = 0;
113 // kDebug()<< "FliteProc::synth: Creating Flite object";
114 m_fliteProc = new K3Process;
115 connect(m_fliteProc, SIGNAL(processExited(K3Process*)),
116 this, SLOT(slotProcessExited(K3Process*)));
117 connect(m_fliteProc, SIGNAL(receivedStdout(K3Process*, char*, int)),
118 this, SLOT(slotReceivedStdout(K3Process*, char*, int)));
119 connect(m_fliteProc, SIGNAL(receivedStderr(K3Process*, char*, int)),
120 this, SLOT(slotReceivedStderr(K3Process*, char*, int)));
121 connect(m_fliteProc, SIGNAL(wroteStdin(K3Process*)),
122 this, SLOT(slotWroteStdin(K3Process* )));
123 if (synthFilename.isNull())
124 m_state = psSaying;
125 else
126 m_state = psSynthing;
128 // Encode quotation characters.
129 QString saidText = text;
131 saidText.replace("\\\"", "#!#!");
132 saidText.replace("\"", "\\\"");
133 saidText.replace("#!#!", "\\\"");
134 // Remove certain comment characters.
135 saidText.replace("--", "");
136 saidText = "\"" + saidText + "\"";
138 saidText += '\n';
140 *m_fliteProc << fliteExePath;
141 // *m_fliteProc << "-t" << saidText;
142 if (!synthFilename.isNull()) *m_fliteProc << "-o" << synthFilename;
144 // Ok, let's rock.
145 m_synthFilename = synthFilename;
146 kDebug() << "FliteProc::synth: Synthing text: '" << saidText << "' using Flite plug in";
147 if (!m_fliteProc->start(K3Process::NotifyOnExit, K3Process::All))
149 kDebug() << "FliteProc::synth: Error starting Flite process. Is flite in the PATH?";
150 m_state = psIdle;
151 return;
153 kDebug()<< "FliteProc:synth: Flite initialized";
154 m_fliteProc->writeStdin(saidText.toLatin1(), saidText.length());
158 * Get the generated audio filename from synthText.
159 * @return Name of the audio file the plugin generated.
160 * Null if no such file.
162 * The plugin must not re-use the filename.
164 QString FliteProc::getFilename()
166 kDebug() << "FliteProc::getFilename: returning " << m_synthFilename;
167 return m_synthFilename;
171 * Stop current operation (saying or synthesizing text).
172 * Important: This function may be called from a thread different from the
173 * one that called sayText or synthText.
174 * If the plugin cannot stop an in-progress @ref sayText or
175 * @ref synthText operation, it must not block waiting for it to complete.
176 * Instead, return immediately.
178 * If a plugin returns before the operation has actually been stopped,
179 * the plugin must emit the @ref stopped signal when the operation has
180 * actually stopped.
182 * The plugin should change to the psIdle state after stopping the
183 * operation.
185 void FliteProc::stopText(){
186 kDebug() << "FliteProc::stopText:: Running";
187 if (m_fliteProc)
189 if (m_fliteProc->isRunning())
191 kDebug() << "FliteProc::stopText: killing Flite.";
192 m_waitingStop = true;
193 m_fliteProc->kill();
194 } else m_state = psIdle;
195 }else m_state = psIdle;
196 kDebug() << "FliteProc::stopText: Flite stopped.";
199 void FliteProc::slotProcessExited(K3Process*)
201 kDebug() << "FliteProc:slotProcessExited: Flite process has exited.";
202 pluginState prevState = m_state;
203 if (m_waitingStop)
205 m_waitingStop = false;
206 m_state = psIdle;
207 emit stopped();
208 } else {
209 m_state = psFinished;
210 if (prevState == psSaying)
211 emit sayFinished();
212 else
213 if (prevState == psSynthing)
214 emit synthFinished();
218 void FliteProc::slotReceivedStdout(K3Process*, char* buffer, int buflen)
220 QString buf = QString::fromLatin1(buffer, buflen);
221 kDebug() << "FliteProc::slotReceivedStdout: Received output from Flite: " << buf;
224 void FliteProc::slotReceivedStderr(K3Process*, char* buffer, int buflen)
226 QString buf = QString::fromLatin1(buffer, buflen);
227 kDebug() << "FliteProc::slotReceivedStderr: Received error from Flite: " << buf;
230 void FliteProc::slotWroteStdin(K3Process*)
232 kDebug() << "FliteProc::slotWroteStdin: closing Stdin";
233 m_fliteProc->closeStdin();
237 * Return the current state of the plugin.
238 * This function only makes sense in asynchronous mode.
239 * @return The pluginState of the plugin.
241 * @see pluginState
243 pluginState FliteProc::getState() { return m_state; }
246 * Acknowledges a finished state and resets the plugin state to psIdle.
248 * If the plugin is not in state psFinished, nothing happens.
249 * The plugin may use this call to do any post-processing cleanup,
250 * for example, blanking the stored filename (but do not delete the file).
251 * Calling program should call getFilename prior to ackFinished.
253 void FliteProc::ackFinished()
255 if (m_state == psFinished)
257 m_state = psIdle;
258 m_synthFilename.clear();
263 * Returns True if the plugin supports asynchronous processing,
264 * i.e., returns immediately from sayText or synthText.
265 * @return True if this plugin supports asynchronous processing.
267 * If the plugin returns True, it must also implement @ref getState .
268 * It must also emit @ref sayFinished or @ref synthFinished signals when
269 * saying or synthesis is completed.
271 bool FliteProc::supportsAsync() { return true; }
274 * Returns True if the plugin supports synthText method,
275 * i.e., is able to synthesize text to a sound file without
276 * audibilizing the text.
277 * @return True if this plugin supports synthText method.
279 bool FliteProc::supportsSynth() { return true; }