Remove this line
[kdeaccessibility.git] / kttsd / libkttsd / pluginproc.h
blob9e77528b5c351cb7a32977b2e119bad9c7a89f23
1 /***************************************************** vim:set ts=4 sw=4 sts=4:
2 This file is the template for the processing plug ins.
3 -------------------
4 Copyright : (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
5 Copyright : (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
6 -------------------
7 Original author: José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
8 Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
9 ******************************************************************************/
11 /***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; version 2 of the License or *
16 * (at your option) version 3. *
17 * *
18 ***************************************************************************/
20 #ifndef PLUGINPROC_H
21 #define PLUGINPROC_H
23 // Qt includes.
24 #include <QtCore/QObject>
26 // KDE includes.
27 #include <kdemacros.h>
28 #include <kconfig.h>
30 /**
31 * @interface PlugInProc
33 * pluginproc - the KDE Text-to-Speech Daemon Plugin API.
35 * @version 1.0 Draft 1
37 * This class defines the interface that plugins to KTTSD must implement.
39 * @warning The pluginproc interface is still being developed and is likely
40 * to change in the future.
42 * A KTTSD Plugin interfaces between KTTSD and a speech engine. It provides the methods
43 * used by KTTSD to synthesize and/or audibilize text into speech.
45 * @section Goals
47 * The ideal plugin has the following features (listed most important to least important):
48 * - It can synthesize text into an audio file without sending the audio to
49 * the audio device. If the plugin can do this, the @ref supportsSynth function
50 * should return True.
51 * - When @ref stopText is called, is able to immediately stop an in-progress
52 * synthesis or saying operation.
53 * - It can operate asynchronously, i.e., returns immediately from a
54 * @ref sayText or @ref synthText call and emits signals @ref sayFinished or
55 * @ref synthFinished when completed. If the plugin can do this, the @ref supportsAsync
56 * function should return True.
58 * As a plugin author, your goal is to provide all 3 of these features. However,
59 * the speech engine you are working with might not be able to support all three
60 * features.
62 * If a plugin cannot do all 3 of the features above, the next best combinations
63 * are (from best to worst):
65 * - @ref supportsSynth returns True, @ref supportsAsync returns False, and
66 * @stopText is able to immediately stop synthesis.
67 * - @ref supportsSynth returns True, @ref supportsAsync returns False, and
68 * @stopText returns immediately without stopping synthesis.
69 * - @ref supportsAsync returns True, @ref supportsSynth returns False, and
70 * @ref stopText is able to immediately stop saying.
71 * - Both @ref supportsSynth and @ref supportsAsync both return False, and
72 * @ref stopText is able to immediately stop saying.
73 * - @ref supportsAsync returns True, @ref supportsSynth returns False, and
74 * @ref stopText returns immediately without stopping saying.
75 * - Both @ref supportsSynth and @ref supportsAsync both return False, and
76 * @ref stopText returns immediately without stopping saying.
78 * Notice that aynchronous support is not essential because KTTSD is able to
79 * provide aynchronous support by running the plugin in a separate thread.
80 * The ability to immediately stop audio output (or support separate synthesis
81 * only) is more important.
83 * @section Minimum Implementations
85 * All plugins should implement @ref init in order to initialize the speech engine,
86 * set language codes, etc.
88 * If @ref supportsSynth return False, a plugin must implement @ref sayText .
90 * If @ref supportsSynth returns True, a plugin must implement the following methods:
91 * - @ref synthText
92 * - @ref getFilename
93 * - @ref ackFinished
94 * The plugin need not implement @ref sayText .
96 * If @ref supportsAsync returns True, the plugin must implement @ref getState .
98 * If @ref supportsAsync returns True, and @ref supportsSynth returns True,
99 * a plugin must emit @ref synthFinished signal when synthesis is completed.
101 * If @ref supportsAsync returns True, and @ref supportsSynth returns False,
102 * a plugin must emit @ref sayFinished signal when saying is completed.
104 * If @ref supportsAsync returns False, do not emit signals @ref sayFinished
105 * or @ref synthFinished .
107 * @section Implementation Guidelines
109 * In no case, will a plugin need to perform more than one @ref sayText or
110 * @ref synthText at a time. In other words, in asynchronous mode, KTTSD will
111 * not call @ref sayText or @ref synthText again until @ref @getState returns
112 * psFinished.
114 * If @ref supportsAsync returns False, KTTSD will run the plugin in a separate
115 * QThread. As a consequence, the plugin must not make use of the KDE Library,
116 * when @ref sayText or @ref synthText is called,
117 * with the exception of K3Process and family (K3ProcIO, K3ShellProcess).
118 * This restriction comes about because the KDE Libraries make use of the
119 * main Qt event loop, which unfortunately, runs only in the main thread.
120 * This restriction will likely be lifted in Qt 4 and later.
122 * Since the KDE library is not available from the @ref sayText and @ref synthText methods,
123 * it is best if the plugin reads configuration settings in the @ref init method.
124 * The KConfig object is passed as an argument to @ref init .
126 * If the synthesis engine requires a long initialization time (more than a second),
127 * it is best if the plugin loads the speech engine from the @ref init method.
128 * Otherwise, it will be more memory efficient to wait until @ref sayText or
129 * @ref synthText is called, because it is possible that the plugin will be created
130 * and initialized, but never used.
132 * All plugins, whether @ref supportsAsync returns True or not, should try to
133 * implement @ref stopText . If a plugin returns False from @ref supportsAsync,
134 * @ref stopText will be called from the main thread, while @ref sayText and/or
135 * @ref synthText will be called from a separate thread. Hence, it will be
136 * possible for @ref stopText to be called while @ref sayText or @ref synthText is
137 * running. Keep this in mind when implementing the code.
139 * If the plugin returns True from @ref supportsAsync, you will of course
140 * need to deal with similar issues. If you have to use QThreads
141 * to implement asynchronous support, do not be concerned about emitting
142 * the @ref sayFinished or @ref synthFinished signals from your threads, since
143 * KTTSD will convert the received signals into postEvents and
144 * return immediately.
146 * If it is not possible for @ref stopText to stop an in-progress operation, it
147 * must not wait for the operation to complete, since this would block KTTSD.
148 * Instead, simply return immediately. Usually, KTTSD will perform other operations
149 * while waiting for the plugin to complete its operation. (See threadedplugin.cpp.)
151 * If the @ref stopText implementation returns before the operation has actually
152 * completed, it must emit the @ref stopped() signal when it is actually completed.
154 * If a plugin returns True from @ref supportsAsync, and @ref stopText is called,
155 * when the plugin has stopped or completed the operation, it must return psIdle
156 * on the next call to @ref getState ; not psFinished. The following state diagram
157 * might be helpful to understand this:
159 @verbatim
160 psIdle <<----------------------------------------------------------
161 / \ ^
162 psSaying psSynthing --- stopText called and operation completed -->> ^
163 \ / ^
164 psFinished --- ackFinished called ------------------------------->> ^
165 @endverbatim
167 * If your plugin can't immediately stop an in-progress operation, the easiest
168 * way to handle this is to set a flag when stopText is called, and then in your
169 * getState() implementation, if the operation has completed, change the
170 * psFinished state to psIdle, if the flag is set. See the flite plugin for
171 * example code.
173 * If a plugin returns True from @ref supportsSynth, KTTSD will pass a suggested
174 * filename in the @ref synthText call. The plugin should synthesize the text
175 * into an audio file with the suggested name. If the synthesis engine does not
176 * permit this, i.e., it will pick a filename of its own, that is OK. In either
177 * case, the actual filename produced should be returned in @ref getFilename .
178 * In no case may the plugin re-use this filename once @ref getFilename has been
179 * called. If for some reason the synthesis engine cannot support this, the
180 * plugin should copy the file to the suggested filename. The file must not be
181 * locked when @ref getFilename is called. The file will be deleted when
182 * KTTSD is finished using it.
184 * The preferred audio file format is wave, since this is the only format
185 * guaranteed to be supported by KDE (aRts). Other formats may or may not be
186 * supported on a user's machine.
188 * The plugin destructor should take care of terminating the speech engine.
190 * @section Error-handling Error Handling
192 * Plugins may emit the @ref error signal when an error occurs.
194 * When an error occurs, plugins should attempt to recover as best they can and
195 * continue accepting @ref sayText or @ref synthText calls. For example,
196 * if a speech engine emits an error in response to certain characters embedded
197 * in synthesizing text, the plugin should discard the text and
198 * emit signal @ref error with True as the first argument and the speech
199 * engine's error message as the second argument. The plugin should then
200 * treat the operation as a completed operation, i.e., return psFinished when
201 * @ref getState is called.
203 * If the speech engine crashes, the plugin should emit signal @ref error with
204 * True as the first argument and then attempt to restart the speech engine.
205 * The plugin will need to implement some protection against an infinite
206 * restart loop and emit the @ref error signal with False as the first argument
207 * if this occurs.
209 * If a plugin emits the @ref error signal with False as the first argument,
210 * KTTSD will no longer call the plugin.
212 * @section PlugInConf
214 * The plugin should implement a configuration dialog where the user can specify
215 * options specific to the speech engine. This dialog is displayed in the KDE
216 * Control Center and also in the KTTS Manager (kttsmgr). See pluginconf.h.
218 * If the user changes any of the settings while the plugin is created,
219 * the plugin will be destroyed and re-created.
222 class QTextCodec;
224 enum pluginState
226 psIdle = 0, /**< Plugin is not doing anything. */
227 psSaying = 1, /**< Plugin is synthesizing and audibilizing. */
228 psSynthing = 2, /**< Plugin is synthesizing. */
229 psFinished = 3 /**< Plugin has finished synthesizing. Audio file is ready. */
232 class KDE_EXPORT PlugInProc : public QObject{
233 Q_OBJECT
235 public:
236 enum CharacterCodec {
237 Local = 0,
238 Latin1 = 1,
239 Unicode = 2,
240 UseCodec = 3
244 * Constructor.
246 explicit PlugInProc( QObject *parent = 0, const char *name = 0);
249 * Destructor.
250 * Plugin must terminate the speech engine.
252 virtual ~PlugInProc();
255 * Initialize the speech engine.
256 * @param config Settings object.
257 * @param configGroup Settings Group.
259 * Sample code for reading configuration:
261 @verbatim
262 config->setGroup(configGroup);
263 m_fliteExePath = config->readEntry("FliteExePath", "flite");
264 kDebug() << "FliteProc::init: path to flite: " << m_fliteExePath;
265 config->setGroup(configGroup);
266 @endverbatim
268 virtual bool init(KConfig *config, const QString &configGroup);
270 /**
271 * Say a text. Synthesize and audibilize it.
272 * @param text The text to be spoken.
274 * If the plugin supports asynchronous operation, it should return immediately
275 * and emit sayFinished signal when synthesis and audibilizing is finished.
276 * It must also implement the @ref getState method, which must return
277 * psFinished, when saying is completed.
279 virtual void sayText(const QString &text);
282 * Synthesize text into an audio file, but do not send to the audio device.
283 * @param text The text to be synthesized.
284 * @param suggestedFilename Full pathname of file to create. The plugin
285 * may ignore this parameter and choose its own
286 * filename. KTTSD will query the generated
287 * filename using getFilename().
289 * If the plugin supports asynchronous operation, it should return immediately
290 * and emit @ref synthFinished signal when synthesis is completed.
291 * It must also implement the @ref getState method, which must return
292 * psFinished, when synthesis is completed.
294 virtual void synthText(const QString &text, const QString &suggestedFilename);
297 * Get the generated audio filename from call to @ref synthText.
298 * @return Name of the audio file the plugin generated.
299 * Null if no such file.
301 * The plugin must not re-use or delete the filename. The file may not
302 * be locked when this method is called. The file will be deleted when
303 * KTTSD is finished using it.
305 virtual QString getFilename();
308 * Stop current operation (saying or synthesizing text).
309 * Important: This function may be called from a thread different from the
310 * one that called sayText or synthText.
311 * If the plugin cannot stop an in-progress @ref sayText or
312 * @ref synthText operation, it must not block waiting for it to complete.
313 * Instead, return immediately.
315 * If a plugin returns before the operation has actually been stopped,
316 * the plugin must emit the @ref stopped signal when the operation has
317 * actually stopped.
319 * The plugin should change to the psIdle state after stopping the
320 * operation.
322 virtual void stopText();
325 * Return the current state of the plugin.
326 * This function only makes sense in asynchronous mode.
327 * @return The pluginState of the plugin.
329 * @see pluginState
331 virtual pluginState getState();
334 * Acknowledges a finished state and resets the plugin state to psIdle.
336 * If the plugin is not in state psFinished, nothing happens.
337 * The plugin may use this call to do any post-processing cleanup,
338 * for example, blanking the stored filename (but do not delete the file).
339 * Calling program should call getFilename prior to ackFinished.
341 virtual void ackFinished();
344 * Returns True if the plugin supports asynchronous processing,
345 * i.e., returns immediately from sayText or synthText.
346 * @return True if this plugin supports asynchronous processing.
348 * If the plugin returns True, it must also implement @ref getState .
349 * It must also emit @ref sayFinished or @ref synthFinished signals when
350 * saying or synthesis is completed.
352 virtual bool supportsAsync();
355 * Returns True if the plugin supports synthText method,
356 * i.e., is able to synthesize text to a sound file without
357 * audibilizing the text.
358 * @return True if this plugin supports synthText method.
360 * If the plugin returns True, it must also implement the following methods:
361 * - @ref synthText
362 * - @ref getFilename
363 * - @ref ackFinished
365 * If the plugin returns True, it need not implement @ref sayText .
367 virtual bool supportsSynth();
370 * Returns the name of an XSLT stylesheet that will convert a valid SSML file
371 * into a format that can be processed by the synth. For example,
372 * The Festival plugin returns a stylesheet that will convert SSML into
373 * SABLE. Any tags the synth cannot handle should be stripped (leaving
374 * their text contents though). The default stylesheet strips all
375 * tags and converts the file to plain text.
376 * @return Name of the XSLT file.
378 virtual QString getSsmlXsltFilename();
381 * Given the name of a codec, returns the QTextCodec for the name.
382 * Handles the following "special" codec names:
383 * Local The user's current Locale codec.
384 * Latin1 Latin1 (ISO 8859-1)
385 * Unicode UTF-16
386 * @param codecName Name of desired codec.
387 * @return The codec object. Calling program must not delete this object
388 * as it is a reference to an existing QTextCodec object.
390 * Caution: Do not pass translated codec names to this routine.
392 static QTextCodec* codecNameToCodec(const QString &codecName);
395 * Builds a list of codec names, suitable for display in a QComboBox.
396 * The list includes the 3 special codec names (translated) at the top:
397 * Local The user's current Locale codec.
398 * Latin1 Latin1 (ISO 8859-1)
399 * Unicode UTF-16
401 static QStringList buildCodecList();
404 * Given the name of a codec, returns index into the codec list.
405 * Handles the following "special" codec names:
406 * Local The user's current Locale codec.
407 * Latin1 Latin1 (ISO 8859-1)
408 * Unicode UTF-16
409 * @param codecName Name of the codec.
410 * @param codecList List of codec names. The first 3 entries may be translated names.
411 * @return QTextCodec object. Caller must not delete this object.
413 * Caution: Do not pass translated codec names to this routine in codecName parameter.
415 static int codecNameToListIndex(const QString &codecName, const QStringList &codecList);
418 * Given index into codec list, returns the codec object.
419 * @param codecNum Index of the codec.
420 * @param codecList List of codec names. The first 3 entries may be translated names.
421 * @return QTextCodec object. Caller must not delete this object.
423 static QTextCodec* codecIndexToCodec(int codecNum, const QStringList &codecList);
426 * Given index into codec list, returns the codec Name.
427 * Handles the following "special" codec names:
428 * Local The user's current Locale codec.
429 * Latin1 Latin1 (ISO 8859-1)
430 * Unicode UTF-16
431 * @param codecNum Index of the codec.
432 * @param codecList List of codec names. The first 3 entries may be translated names.
433 * @return Untranslated name of the codec.
435 static QString codecIndexToCodecName(int codecNum, const QStringList &codecList);
437 signals:
439 * Emitted when synthText() finishes and plugin supports asynchronous mode.
441 void synthFinished();
443 * Emitted when sayText() finishes and plugin supports asynchronous mode.
445 void sayFinished();
447 * Emitted when stopText() has been called and plugin stops asynchronously.
449 void stopped();
451 * Emitted if an error occurs.
452 * @param keepGoing True if the plugin can continue processing.
453 * False if the plugin cannot continue, for example,
454 * the speech engine could not be started.
455 * @param msg Error message.
457 * When an error occurs, plugins should attempt to recover as best they can
458 * and continue accepting @ref sayText or @ref synthText calls. For example,
459 * if the speech engine emits an error while synthesizing text, the plugin
460 * should return True along with error message.
462 * @see Error-handling
465 void error(bool keepGoing, const QString &msg);
468 #endif // PLUGINPROC_H