From 00bb99ac80741fc50ef8a289719373032f2391eb Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeaccessibility@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kttsd/libkttsd/pluginproc.h | 466 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 466 insertions(+) create mode 100644 kttsd/libkttsd/pluginproc.h (limited to 'kttsd/libkttsd/pluginproc.h') diff --git a/kttsd/libkttsd/pluginproc.h b/kttsd/libkttsd/pluginproc.h new file mode 100644 index 0000000..c271ad3 --- /dev/null +++ b/kttsd/libkttsd/pluginproc.h @@ -0,0 +1,466 @@ +/***************************************************** vim:set ts=4 sw=4 sts=4: + This file is the template for the processing plug ins. + ------------------- + Copyright : (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández + Copyright : (C) 2004 by Gary Cramblitt + ------------------- + Original author: José Pablo Ezequiel "Pupeno" Fernández + Current Maintainer: Gary Cramblitt + ******************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ + +#ifndef _PLUGINPROC_H_ +#define _PLUGINPROC_H_ + +#include +#include +#include +#include "kdeexportfix.h" +#include + +/** +* @interface PlugInProc +* +* pluginproc - the KDE Text-to-Speech Deamon Plugin API. +* +* @version 1.0 Draft 1 +* +* This class defines the interface that plugins to KTTSD must implement. +* +* @warning The pluginproc interface is still being developed and is likely +* to change in the future. +* +* A KTTSD Plugin interfaces between KTTSD and a speech engine. It provides the methods +* used by KTTSD to synthesize and/or audibilize text into speech. +* +* @section Goals +* +* The ideal plugin has the following features (listed most important to least important): +* - It can synthesize text into an audio file without sending the audio to +* the audio device. If the plugin can do this, the @ref supportsSynth function +* should return True. +* - When @ref stopText is called, is able to immediately stop an in-progress +* synthesis or saying operation. +* - It can operate asynchronously, i.e., returns immediately from a +* @ref sayText or @ref synthText call and emits signals @ref sayFinished or +* @ref synthFinished when completed. If the plugin can do this, the @ref supportsAsync +* function should return True. +* +* As a plugin author, your goal is to provide all 3 of these features. However, +* the speech engine you are working with might not be able to support all three +* features. +* +* If a plugin cannot do all 3 of the features above, the next best combinations +* are (from best to worst): +* +* - @ref supportsSynth returns True, @ref supportsAsync returns False, and +* @stopText is able to immediately stop synthesis. +* - @ref supportsSynth returns True, @ref supportsAsync returns False, and +* @stopText returns immediately without stopping synthesis. +* - @ref supportsAsync returns True, @ref supportsSynth returns False, and +* @ref stopText is able to immediately stop saying. +* - Both @ref supportsSynth and @ref supportsAsync both return False, and +* @ref stopText is able to immediately stop saying. +* - @ref supportsAsync returns True, @ref supportsSynth returns False, and +* @ref stopText returns immediately without stopping saying. +* - Both @ref supportsSynth and @ref supportsAsync both return False, and +* @ref stopText returns immediately without stopping saying. +* +* Notice that aynchronous support is not essential because KTTSD is able to +* provide aynchronous support by running the plugin in a separate thread. +* The ability to immediately stop audio output (or support separate synthesis +* only) is more important. +* +* @section Minimum Implementations +* +* All plugins should implement @ref init in order to initialize the speech engine, +* set language codes, etc. +* +* If @ref supportsSynth return False, a plugin must implement @ref sayText . +* +* If @ref supportsSynth returns True, a plugin must implement the following methods: +* - @ref synthText +* - @ref getFilename +* - @ref ackFinished +* The plugin need not implement @ref sayText . +* +* If @ref supportsAsync returns True, the plugin must implement @ref getState . +* +* If @ref supportsAsync returns True, and @ref supportsSynth returns True, +* a plugin must emit @ref synthFinished signal when synthesis is completed. +* +* If @ref supportsAsync returns True, and @ref supportsSynth returns False, +* a plugin must emit @ref sayFinished signal when saying is completed. +* +* If @ref supportsAsync returns False, do not emit signals @ref sayFinished +* or @ref synthFinished . +* +* @section Implementation Guidelines +* +* In no case, will a plugin need to perform more than one @ref sayText or +* @ref synthText at a time. In other words, in asynchronous mode, KTTSD will +* not call @ref sayText or @ref synthText again until @ref @getState returns +* psFinished. +* +* If @ref supportsAsync returns False, KTTSD will run the plugin in a separate +* QThread. As a consequence, the plugin must not make use of the KDE Library, +* when @ref sayText or @ref synthText is called, +* with the exception of KProcess and family (KProcIO, KShellProcess). +* This restriction comes about because the KDE Libraries make use of the +* main Qt event loop, which unfortunately, runs only in the main thread. +* This restriction will likely be lifted in Qt 4 and later. +* +* Since the KDE library is not available from the @ref sayText and @ref synthText methods, +* it is best if the plugin reads configuration settings in the @ref init method. +* The KConfig object is passed as an argument to @ref init . +* +* If the synthesis engine requires a long initialization time (more than a second), +* it is best if the plugin loads the speech engine from the @ref init method. +* Otherwise, it will be more memory efficient to wait until @ref sayText or +* @ref synthText is called, because it is possible that the plugin will be created +* and initialized, but never used. +* +* All plugins, whether @ref supportsAsync returns True or not, should try to +* implement @ref stopText . If a plugin returns False from @ref supportsAsync, +* @ref stopText will be called from the main thread, while @ref sayText and/or +* @ref synthText will be called from a separate thread. Hence, it will be +* possible for @ref stopText to be called while @ref sayText or @ref synthText is +* running. Keep this in mind when implementing the code. +* +* If the plugin returns True from @ref supportsAsync, you will of course +* need to deal with similar issues. If you have to use QThreads +* to implement asynchronous support, do not be concerned about emitting +* the @ref sayFinished or @ref synthFinished signals from your threads, since +* KTTSD will convert the received signals into postEvents and +* return immediately. +* +* If it is not possible for @ref stopText to stop an in-progress operation, it +* must not wait for the operation to complete, since this would block KTTSD. +* Instead, simply return immediately. Usually, KTTSD will perform other operations +* while waiting for the plugin to complete its operation. (See threadedplugin.cpp.) +* +* If the @ref stopText implementation returns before the operation has actually +* completed, it must emit the @ref stopped() signal when it is actually completed. +* +* If a plugin returns True from @ref supportsAsync, and @ref stopText is called, +* when the plugin has stopped or completed the operation, it must return psIdle +* on the next call to @ref getState ; not psFinished. The following state diagram +* might be helpful to understand this: +* + @verbatim + psIdle <<---------------------------------------------------------- + / \ ^ + psSaying psSynthing --- stopText called and operation completed -->> ^ + \ / ^ + psFinished --- ackFinished called ------------------------------->> ^ + @endverbatim +* +* If your plugin can't immediately stop an in-progress operation, the easiest +* way to handle this is to set a flag when stopText is called, and then in your +* getState() implementation, if the operation has completed, change the +* psFinished state to psIdle, if the flag is set. See the flite plugin for +* example code. +* +* If a plugin returns True from @ref supportsSynth, KTTSD will pass a suggested +* filename in the @ref synthText call. The plugin should synthesize the text +* into an audio file with the suggested name. If the synthesis engine does not +* permit this, i.e., it will pick a filename of its own, that is OK. In either +* case, the actual filename produced should be returned in @ref getFilename . +* In no case may the plugin re-use this filename once @ref getFilename has been +* called. If for some reason the synthesis engine cannot support this, the +* plugin should copy the file to the suggested filename. The file must not be +* locked when @ref getFilename is called. The file will be deleted when +* KTTSD is finished using it. +* +* The preferred audio file format is wave, since this is the only format +* guaranteed to be supported by KDE (aRts). Other formats may or may not be +* supported on a user's machine. +* +* The plugin destructor should take care of terminating the speech engine. +* +* @section Error-handling Error Handling +* +* Plugins may emit the @ref error signal when an error occurs. +* +* When an error occurs, plugins should attempt to recover as best they can and +* continue accepting @ref sayText or @ref synthText calls. For example, +* if a speech engine emits an error in response to certain characters embedded +* in synthesizing text, the plugin should discard the text and +* emit signal @ref error with True as the first argument and the speech +* engine's error message as the second argument. The plugin should then +* treat the operation as a completed operation, i.e., return psFinished when +* @ref getState is called. +* +* If the speech engine crashes, the plugin should emit signal @ref error with +* True as the first argument and then attempt to restart the speech engine. +* The plugin will need to implement some protection against an infinite +* restart loop and emit the @ref error signal with False as the first argument +* if this occurs. +* +* If a plugin emits the @ref error signal with False as the first argument, +* KTTSD will no longer call the plugin. +* +* @section PlugInConf +* +* The plugin should implement a configuration dialog where the user can specify +* options specific to the speech engine. This dialog is displayed in the KDE +* Control Center and also in the KTTS Manager (kttsmgr). See pluginconf.h. +* +* If the user changes any of the settings while the plugin is created, +* the plugin will be destroyed and re-created. +*/ + +class QTextCodec; + +enum pluginState +{ + psIdle = 0, /**< Plugin is not doing anything. */ + psSaying = 1, /**< Plugin is synthesizing and audibilizing. */ + psSynthing = 2, /**< Plugin is synthesizing. */ + psFinished = 3 /**< Plugin has finished synthesizing. Audio file is ready. */ +}; + +class KDE_EXPORT PlugInProc : virtual public QObject{ + Q_OBJECT + + public: + enum CharacterCodec { + Local = 0, + Latin1 = 1, + Unicode = 2, + UseCodec = 3 + }; + + /** + * Constructor. + */ + PlugInProc( QObject *parent = 0, const char *name = 0); + + /** + * Destructor. + * Plugin must terminate the speech engine. + */ + virtual ~PlugInProc(); + + /** + * Initialize the speech engine. + * @param config Settings object. + * @param configGroup Settings Group. + * + * Sample code for reading configuration: + * + @verbatim + config->setGroup(configGroup); + m_fliteExePath = config->readEntry("FliteExePath", "flite"); + kdDebug() << "FliteProc::init: path to flite: " << m_fliteExePath << endl; + config->setGroup(configGroup); + @endverbatim + */ + virtual bool init(KConfig *config, const QString &configGroup); + + /** + * Say a text. Synthesize and audibilize it. + * @param text The text to be spoken. + * + * If the plugin supports asynchronous operation, it should return immediately + * and emit sayFinished signal when synthesis and audibilizing is finished. + * It must also implement the @ref getState method, which must return + * psFinished, when saying is completed. + */ + virtual void sayText(const QString &text); + + /** + * Synthesize text into an audio file, but do not send to the audio device. + * @param text The text to be synthesized. + * @param suggestedFilename Full pathname of file to create. The plugin + * may ignore this parameter and choose its own + * filename. KTTSD will query the generated + * filename using getFilename(). + * + * If the plugin supports asynchronous operation, it should return immediately + * and emit @ref synthFinished signal when synthesis is completed. + * It must also implement the @ref getState method, which must return + * psFinished, when synthesis is completed. + */ + virtual void synthText(const QString &text, const QString &suggestedFilename); + + /** + * Get the generated audio filename from call to @ref synthText. + * @return Name of the audio file the plugin generated. + * Null if no such file. + * + * The plugin must not re-use or delete the filename. The file may not + * be locked when this method is called. The file will be deleted when + * KTTSD is finished using it. + */ + virtual QString getFilename(); + + /** + * Stop current operation (saying or synthesizing text). + * Important: This function may be called from a thread different from the + * one that called sayText or synthText. + * If the plugin cannot stop an in-progress @ref sayText or + * @ref synthText operation, it must not block waiting for it to complete. + * Instead, return immediately. + * + * If a plugin returns before the operation has actually been stopped, + * the plugin must emit the @ref stopped signal when the operation has + * actually stopped. + * + * The plugin should change to the psIdle state after stopping the + * operation. + */ + virtual void stopText(); + + /** + * Return the current state of the plugin. + * This function only makes sense in asynchronous mode. + * @return The pluginState of the plugin. + * + * @see pluginState + */ + virtual pluginState getState(); + + /** + * Acknowledges a finished state and resets the plugin state to psIdle. + * + * If the plugin is not in state psFinished, nothing happens. + * The plugin may use this call to do any post-processing cleanup, + * for example, blanking the stored filename (but do not delete the file). + * Calling program should call getFilename prior to ackFinished. + */ + virtual void ackFinished(); + + /** + * Returns True if the plugin supports asynchronous processing, + * i.e., returns immediately from sayText or synthText. + * @return True if this plugin supports asynchronous processing. + * + * If the plugin returns True, it must also implement @ref getState . + * It must also emit @ref sayFinished or @ref synthFinished signals when + * saying or synthesis is completed. + */ + virtual bool supportsAsync(); + + /** + * Returns True if the plugin supports synthText method, + * i.e., is able to synthesize text to a sound file without + * audibilizing the text. + * @return True if this plugin supports synthText method. + * + * If the plugin returns True, it must also implement the following methods: + * - @ref synthText + * - @ref getFilename + * - @ref ackFinished + * + * If the plugin returns True, it need not implement @ref sayText . + */ + virtual bool supportsSynth(); + + /** + * Returns the name of an XSLT stylesheet that will convert a valid SSML file + * into a format that can be processed by the synth. For example, + * The Festival plugin returns a stylesheet that will convert SSML into + * SABLE. Any tags the synth cannot handle should be stripped (leaving + * their text contents though). The default stylesheet strips all + * tags and converts the file to plain text. + * @return Name of the XSLT file. + */ + virtual QString getSsmlXsltFilename(); + + /** + * Given the name of a codec, returns the QTextCodec for the name. + * Handles the following "special" codec names: + * Local The user's current Locale codec. + * Latin1 Latin1 (ISO 8859-1) + * Unicode UTF-16 + * @param codecName Name of desired codec. + * @return The codec object. Calling program must not delete this object + * as it is a reference to an existing QTextCodec object. + * + * Caution: Do not pass translated codec names to this routine. + */ + static QTextCodec* codecNameToCodec(const QString &codecName); + + /** + * Builds a list of codec names, suitable for display in a QComboBox. + * The list includes the 3 special codec names (translated) at the top: + * Local The user's current Locale codec. + * Latin1 Latin1 (ISO 8859-1) + * Unicode UTF-16 + */ + static QStringList buildCodecList(); + + /** + * Given the name of a codec, returns index into the codec list. + * Handles the following "special" codec names: + * Local The user's current Locale codec. + * Latin1 Latin1 (ISO 8859-1) + * Unicode UTF-16 + * @param codecName Name of the codec. + * @param codecList List of codec names. The first 3 entries may be translated names. + * @return QTextCodec object. Caller must not delete this object. + * + * Caution: Do not pass translated codec names to this routine in codecName parameter. + */ + static int codecNameToListIndex(const QString &codecName, const QStringList &codecList); + + /** + * Given index into codec list, returns the codec object. + * @param codecNum Index of the codec. + * @param codecList List of codec names. The first 3 entries may be translated names. + * @return QTextCodec object. Caller must not delete this object. + */ + static QTextCodec* codecIndexToCodec(int codecNum, const QStringList &codecList); + + /** + * Given index into codec list, returns the codec Name. + * Handles the following "special" codec names: + * Local The user's current Locale codec. + * Latin1 Latin1 (ISO 8859-1) + * Unicode UTF-16 + * @param codecNum Index of the codec. + * @param codecList List of codec names. The first 3 entries may be translated names. + * @return Untranslated name of the codec. + */ + static QString codecIndexToCodecName(int codecNum, const QStringList &codecList); + + signals: + /** + * Emitted when synthText() finishes and plugin supports asynchronous mode. + */ + void synthFinished(); + /** + * Emitted when sayText() finishes and plugin supports asynchronous mode. + */ + void sayFinished(); + /** + * Emitted when stopText() has been called and plugin stops asynchronously. + */ + void stopped(); + /** + * Emitted if an error occurs. + * @param keepGoing True if the plugin can continue processing. + * False if the plugin cannot continue, for example, + * the speech engine could not be started. + * @param msg Error message. + * + * When an error occurs, plugins should attempt to recover as best they can + * and continue accepting @ref sayText or @ref synthText calls. For example, + * if the speech engine emits an error while synthesizing text, the plugin + * should return True along with error message. + * + * @see Error-handling + * + */ + void error(bool keepGoing, const QString &msg); +}; + +#endif // _PLUGINPROC_H_ -- cgit v1.2.1