diff options
author | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
---|---|---|
committer | toma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2009-11-25 17:56:58 +0000 |
commit | 00bb99ac80741fc50ef8a289719373032f2391eb (patch) | |
tree | 3a5a9bf72f942784b38bf77dd66c534662fab5f2 /kttsd/plugins/freetts | |
download | tdeaccessibility-00bb99ac80741fc50ef8a289719373032f2391eb.tar.gz tdeaccessibility-00bb99ac80741fc50ef8a289719373032f2391eb.zip |
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
Diffstat (limited to 'kttsd/plugins/freetts')
-rw-r--r-- | kttsd/plugins/freetts/Makefile.am | 18 | ||||
-rw-r--r-- | kttsd/plugins/freetts/README | 6 | ||||
-rw-r--r-- | kttsd/plugins/freetts/configure.in.bot | 15 | ||||
-rw-r--r-- | kttsd/plugins/freetts/configure.in.in | 22 | ||||
-rw-r--r-- | kttsd/plugins/freetts/freettsconf.cpp | 230 | ||||
-rw-r--r-- | kttsd/plugins/freetts/freettsconf.h | 122 | ||||
-rw-r--r-- | kttsd/plugins/freetts/freettsconfigwidget.ui | 200 | ||||
-rw-r--r-- | kttsd/plugins/freetts/freettsplugin.cpp | 26 | ||||
-rw-r--r-- | kttsd/plugins/freetts/freettsproc.cpp | 275 | ||||
-rw-r--r-- | kttsd/plugins/freetts/freettsproc.h | 180 | ||||
-rw-r--r-- | kttsd/plugins/freetts/kttsd_freettsplugin.desktop | 51 |
11 files changed, 1145 insertions, 0 deletions
diff --git a/kttsd/plugins/freetts/Makefile.am b/kttsd/plugins/freetts/Makefile.am new file mode 100644 index 0000000..be9312b --- /dev/null +++ b/kttsd/plugins/freetts/Makefile.am @@ -0,0 +1,18 @@ +INCLUDES = \ + -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \ + $(all_includes) + +METASOURCES = AUTO + +kde_module_LTLIBRARIES = libkttsd_freettsplugin.la + +libkttsd_freettsplugin_la_SOURCES = \ + freettsconfigwidget.ui \ + freettsconf.cpp \ + freettsproc.cpp \ + freettsplugin.cpp +libkttsd_freettsplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries) +libkttsd_freettsplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la + +services_DATA = kttsd_freettsplugin.desktop +servicesdir = $(kde_servicesdir) diff --git a/kttsd/plugins/freetts/README b/kttsd/plugins/freetts/README new file mode 100644 index 0000000..54d9dc2 --- /dev/null +++ b/kttsd/plugins/freetts/README @@ -0,0 +1,6 @@ +This is the directory containing the FreeTTS plug in. +If you intend to edit the GUI (freettsconfig.ui) you will have to first +copy kttsd/libkttsd/pluginconf.h to a standard include directory +like $KDEDIR/include/ since the interface has been tweaked to derive +from PlugInConf instead of QWidget and Qt Designer refuses to open it +if the header is not properly place. diff --git a/kttsd/plugins/freetts/configure.in.bot b/kttsd/plugins/freetts/configure.in.bot new file mode 100644 index 0000000..b3985b9 --- /dev/null +++ b/kttsd/plugins/freetts/configure.in.bot @@ -0,0 +1,15 @@ +if test "x$freetts_bindir" = "xno"; then + if test "$compile_freetts_plugin" = "yes"; then + echo "" + echo "======================================================" + echo "The freetts.jar Java archive has not been found on" + echo "this system. The FreeTTS plugin will be built, " + echo "but you must install FreeTTS it before you can use it," + echo "or if it already installed you must set the path to" + echo "it in the KDE Text-to-Speech Manager." + echo "FreeTTS is available from freetts.sourceforge.net" + echo "=====================================================" + all_tests=bad + fi +fi + diff --git a/kttsd/plugins/freetts/configure.in.in b/kttsd/plugins/freetts/configure.in.in new file mode 100644 index 0000000..78555fc --- /dev/null +++ b/kttsd/plugins/freetts/configure.in.in @@ -0,0 +1,22 @@ +dnl ================ +dnl checks for FreeTTS +dnl ================ + +AC_ARG_ENABLE(kttsd-freetts, + AC_HELP_STRING([--enable-kttsd-freetts], + [build KTTSD FreeTTS Plugin [default=yes]]), + freetts_plugin=$enableval, + freetts_plugin=yes) + +compile_freetts_plugin="yes" + +if test "x$freetts_plugin" = "xno"; then + compile_freetts_plugin="no" +fi + +dnl Check for festival executable. +dnl Note that Festival Interactive plugin is always built +dnl whether binary is found or not, unless user overrides with -disable-freetts. +AC_PATH_PROG(freetts_bindir, "freetts.jar", "no") + +AM_CONDITIONAL(include_kttsd_freetts, test "x$compile_freetts_plugin" = "xyes") diff --git a/kttsd/plugins/freetts/freettsconf.cpp b/kttsd/plugins/freetts/freettsconf.cpp new file mode 100644 index 0000000..701af5e --- /dev/null +++ b/kttsd/plugins/freetts/freettsconf.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** + Configuration widget and functions for FreeTTS (interactive) plug in + ------------------- + Copyright : (C) 2004 Paul Giannaros + ------------------- + Original author: Paul Giannaros <ceruleanblaze@gmail.com> + Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com> + ******************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +// Qt includes. +#include <qlayout.h> +#include <qlabel.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qfile.h> +#include <qapplication.h> + +// KDE includes. +#include <kdialog.h> +#include <ktempfile.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kprogress.h> + +// KTTS includes. +#include <pluginconf.h> +#include <testplayer.h> + +// FreeTTS includes. +#include "freettsconf.h" +#include "freettsconfigwidget.h" + +/** Constructor */ +FreeTTSConf::FreeTTSConf( QWidget* parent, const char* name, const QStringList&/*args*/) : + PlugInConf( parent, name ) { + + // kdDebug() << "FreeTTSConf::FreeTTSConf: Running" << endl; + m_freettsProc = 0; + m_progressDlg = 0; + + QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(), + KDialog::spacingHint(), "FreeTTSConfigWidgetLayout"); + layout->setAlignment (Qt::AlignTop); + m_widget = new FreeTTSConfWidget(this, "FreeTTSConfigWidget"); + layout->addWidget(m_widget); + + defaults(); + + connect(m_widget->freettsPath, SIGNAL(textChanged(const QString&)), + this, SLOT(configChanged())); + connect(m_widget->freettsTest, SIGNAL(clicked()), this, SLOT(slotFreeTTSTest_clicked())); +} + +/** Destructor */ +FreeTTSConf::~FreeTTSConf() { + // kdDebug() << "Running: FreeTTSConf::~FreeTTSConf()" << endl; + if (!m_waveFile.isNull()) QFile::remove(m_waveFile); + delete m_freettsProc; + delete m_progressDlg; +} + +void FreeTTSConf::load(KConfig *config, const QString &configGroup) { + // kdDebug() << "FreeTTSConf::load: Running" << endl; + + config->setGroup(configGroup); + QString freeTTSJar = config->readEntry("FreeTTSJarPath", QString::null); + if (freeTTSJar.isEmpty()) + { + config->setGroup("FreeTTS"); + freeTTSJar = config->readEntry("FreeTTSJarPath", QString::null); + } + if (freeTTSJar.isEmpty()) + freeTTSJar = getLocation("freetts.jar"); + m_widget->freettsPath->setURL(freeTTSJar); + /// If freettsPath is still empty, then we couldn't find the file in the path. +} + +void FreeTTSConf::save(KConfig *config, const QString &configGroup){ + // kdDebug() << "FreeTTSConf::save: Running" << endl; + + config->setGroup("FreeTTS"); + config->writeEntry("FreeTTSJarPath", + realFilePath(m_widget->freettsPath->url())); + + config->setGroup(configGroup); + if(m_widget->freettsPath->url().isEmpty()) + KMessageBox::sorry(0, i18n("Unable to locate freetts.jar in your path.\nPlease specify the path to freetts.jar in the Properties tab before using KDE Text-to-Speech"), i18n("KDE Text-to-Speech")); + config->writeEntry("FreeTTSJarPath", + realFilePath(m_widget->freettsPath->url())); +} + +void FreeTTSConf::defaults(){ + // kdDebug() << "Running: FreeTTSConf::defaults()" << endl; + m_widget->freettsPath->setURL(""); +} + +void FreeTTSConf::setDesiredLanguage(const QString &lang) +{ + m_languageCode = lang; +} + +QString FreeTTSConf::getTalkerCode() +{ + QString freeTTSJar = realFilePath(m_widget->freettsPath->url()); + if (!freeTTSJar.isEmpty()) + { + if (!getLocation(freeTTSJar).isEmpty()) + { + return QString( + "<voice lang=\"%1\" name=\"%2\" gender=\"%3\" />" + "<prosody volume=\"%4\" rate=\"%5\" />" + "<kttsd synthesizer=\"%6\" />") + .arg(m_languageCode) + .arg("fixed") + .arg("neutral") + .arg("medium") + .arg("medium") + .arg("FreeTTS"); + } + } + return QString::null; +} + +// QString FreeTTSConf::getLocation(const QString &name) { +// /// Iterate over the path and see if 'name' exists in it. Return the +// /// full path to it if it does. Else return an empty QString. +// kdDebug() << "FreeTTSConf::getLocation: Searching for " << name << " in the path... " << endl; +// kdDebug() << m_path << endl; +// for(QStringList::iterator it = m_path.begin(); it != m_path.end(); ++it) { +// QString fullName = *it; +// fullName += "/"; +// fullName += name; +// /// The user either has the directory of the file in the path... +// if(QFile::exists(fullName)) { +// return fullName; +// kdDebug() << fullName << endl; +// } +// /// ....Or the file itself +// else if(QFileInfo(*it).baseName().append(QString(".").append(QFileInfo(*it).extension())) == name) { +// return fullName; +// kdDebug() << fullName << endl; +// } +// } +// return ""; +// } + + +void FreeTTSConf::slotFreeTTSTest_clicked() +{ + // kdDebug() << "FreeTTSConf::slotFreeTTSTest_clicked(): Running" << endl; + // If currently synthesizing, stop it. + if (m_freettsProc) + m_freettsProc->stopText(); + else + { + m_freettsProc = new FreeTTSProc(); + connect (m_freettsProc, SIGNAL(stopped()), this, SLOT(slotSynthStopped())); + } + // Create a temp file name for the wave file. + KTempFile tempFile (locateLocal("tmp", "freettsplugin-"), ".wav"); + QString tmpWaveFile = tempFile.file()->name(); + tempFile.close(); + + // Get test message in the language of the voice. + QString testMsg = testMessage(m_languageCode); + + // Tell user to wait. + m_progressDlg = new KProgressDialog(m_widget, "kttsmgr_freetts_testdlg", + i18n("Testing"), + i18n("Testing."), + true); + m_progressDlg->progressBar()->hide(); + m_progressDlg->setAllowCancel(true); + + // I think FreeTTS only officialy supports English, but if anyone knows of someone + // whos built up a different language lexicon and has it working with FreeTTS gimme an email at ceruleanblaze@gmail.com + connect (m_freettsProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished())); + m_freettsProc->synth( + testMsg, + tmpWaveFile, + realFilePath(m_widget->freettsPath->url())); + + // Display progress dialog modally. Processing continues when plugin signals synthFinished, + // or if user clicks Cancel button. + m_progressDlg->exec(); + disconnect (m_freettsProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished())); + if (m_progressDlg->wasCancelled()) m_freettsProc->stopText(); + delete m_progressDlg; + m_progressDlg = 0; +} + +void FreeTTSConf::slotSynthFinished() +{ + // If user canceled, progress dialog is gone, so exit. + if (!m_progressDlg) + { + m_freettsProc->ackFinished(); + return; + } + // Hide the Cancel button so user can't cancel in the middle of playback. + m_progressDlg->showCancelButton(false); + // Get new wavefile name. + m_waveFile = m_freettsProc->getFilename(); + // Tell synth we're done. + m_freettsProc->ackFinished(); + // Play the wave file (possibly adjusting its Speed). + // Player object deletes the wave file when done. + if (m_player) m_player->play(m_waveFile); + QFile::remove(m_waveFile); + m_waveFile = QString::null; + if (m_progressDlg) m_progressDlg->close(); +} + +void FreeTTSConf::slotSynthStopped() +{ + // Clean up after canceling test. + QString filename = m_freettsProc->getFilename(); + if (!filename.isNull()) QFile::remove(filename); +} + +#include "freettsconf.moc" diff --git a/kttsd/plugins/freetts/freettsconf.h b/kttsd/plugins/freetts/freettsconf.h new file mode 100644 index 0000000..9ab3ae8 --- /dev/null +++ b/kttsd/plugins/freetts/freettsconf.h @@ -0,0 +1,122 @@ +/**************************************************************************** + Configuration widget and functions for FreeTTS (interactive) plug in + ------------------- + Copyright : (C) 2004 Paul Giannaros + ------------------- + Original author: Paul Giannaros <ceruleanblaze@gmail.com> + Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com> + ******************************************************************************/ + +/*************************************************************************** + * * + * 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 _FREETTSCONF_H_ +#define _FREETTSCONF_H_ + +#include <qstringlist.h> + +#include <kdebug.h> +#include <kconfig.h> + +#include <pluginconf.h> + +#include "freettsconfigwidget.h" +#include "freettsproc.h" + +class QStringList; +class KProgressDialog; + +class FreeTTSConf : public PlugInConf { + Q_OBJECT + + public: + /** Constructor */ + FreeTTSConf( QWidget* parent = 0, const char* name = 0, const QStringList &args = QStringList()); + + /** Destructor */ + ~FreeTTSConf(); + + /** This method is invoked whenever the module should read its + configuration (most of the times from a config file) and update the + user interface. This happens when the user clicks the "Reset" button in + the control center, to undo all of his changes and restore the currently + valid settings. NOTE that this is not called after the modules is loaded, + so you probably want to call this method in the constructor.*/ + void load(KConfig *config, const QString &configGroup); + + /** This function gets called when the user wants to save the settings in + the user interface, updating the config files or wherever the + configuration is stored. The method is called when the user clicks "Apply" + or "Ok". */ + void save(KConfig *config, const QString &configGroup); + + /** This function is called to set the settings in the module to sensible + default values. It gets called when hitting the "Default" button. The + default values should probably be the same as the ones the application + uses when started without a config file. */ + void defaults(); + + /** + * This function informs the plugin of the desired language to be spoken + * by the plugin. The plugin should attempt to adapt itself to the + * specified language code, choosing sensible defaults if necessary. + * If the passed-in code is QString::null, no specific language has + * been chosen. + * @param lang The desired language code or Null if none. + * + * If the plugin is unable to support the desired language, that is OK. + * Language codes are given by ISO 639-1 and are in lowercase. + * The code may also include an ISO 3166 country code in uppercase + * separated from the language code by underscore (_). For + * example, en_GB. If your plugin supports the given language, but + * not the given country, treat it as though the country + * code were not specified, i.e., adapt to the given language. + */ + void setDesiredLanguage(const QString &lang); + + /** + * Return fully-specified talker code for the configured plugin. This code + * uniquely identifies the configured instance of the plugin and distinquishes + * one instance from another. If the plugin has not been fully configured, + * i.e., cannot yet synthesize, return QString::null. + * @return Fully-specified talker code. + */ + QString getTalkerCode(); + + /** + * Function searches the $PATH for a file. If it exists, it returns the full path + * to that file. If not, then it returns an empty QString. + * @param name The name of the file to search for. + * @returns The full path to the file or an empty QString. + */ + + private slots: + void configChanged(bool t = true) { + emit changed(t); + }; + void slotFreeTTSTest_clicked(); + void slotSynthFinished(); + void slotSynthStopped(); + + private: + /// Language code. + QString m_languageCode; + + /// Configuration Widget. + FreeTTSConfWidget *m_widget; + + /// FreeTTS synthesizer. + FreeTTSProc *m_freettsProc; + + /// Synthesized wave file name. + QString m_waveFile; + + /// Progress dialog. + KProgressDialog* m_progressDlg; +}; +#endif diff --git a/kttsd/plugins/freetts/freettsconfigwidget.ui b/kttsd/plugins/freetts/freettsconfigwidget.ui new file mode 100644 index 0000000..1d95751 --- /dev/null +++ b/kttsd/plugins/freetts/freettsconfigwidget.ui @@ -0,0 +1,200 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>FreeTTSConfWidget</class> +<author>Gary Cramblitt <garycramblitt@comcast.net></author> +<widget class="QWidget"> + <property name="name"> + <cstring>FreeTTSConfWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>576</width> + <height>134</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>FreeTTS Config UI</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>freettsConfigurationBox</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>GroupBoxPanel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="title"> + <string>FreeTTS Interactive Configuration</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>voicesPathBox</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>freettsPathLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>&FreeTTS jar file:</string> + </property> + <property name="textFormat"> + <enum>AutoText</enum> + </property> + <property name="alignment"> + <set>AlignVCenter|AlignRight</set> + </property> + <property name="buddy" stdset="0"> + <cstring>freettsPath</cstring> + </property> + </widget> + <widget class="KURLRequester"> + <property name="name"> + <cstring>freettsPath</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>selectVoiceBox</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + </hbox> + </widget> + <widget class="QLayoutWidget" row="3" column="0"> + <property name="name"> + <cstring>layout10</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>410</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>freettsTest</cstring> + </property> + <property name="text"> + <string>Test</string> + </property> + </widget> + </hbox> + </widget> + </grid> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<includes> + <include location="global" impldecl="in declaration">kurlrequester.h</include> + <include location="global" impldecl="in implementation">kurlrequester.h</include> +</includes> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/kttsd/plugins/freetts/freettsplugin.cpp b/kttsd/plugins/freetts/freettsplugin.cpp new file mode 100644 index 0000000..c8a75df --- /dev/null +++ b/kttsd/plugins/freetts/freettsplugin.cpp @@ -0,0 +1,26 @@ +/**************************************************************************** + Factory generation for the FreeTTS plugin so it can actually be used + as such. + ------------------- + Copyright : (C) 2004 Paul Giannaros + ------------------- + Original author: Paul Giannaros <ceruleanblaze@gmail.com> + Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com> + ******************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include <kgenericfactory.h> + +#include "freettsconf.h" +#include "freettsproc.h" + +typedef K_TYPELIST_2( FreeTTSProc, FreeTTSConf ) FreeTTS; +K_EXPORT_COMPONENT_FACTORY( libkttsd_freettsplugin, KGenericFactory<FreeTTS>("kttsd_freetts")) + diff --git a/kttsd/plugins/freetts/freettsproc.cpp b/kttsd/plugins/freetts/freettsproc.cpp new file mode 100644 index 0000000..829fee9 --- /dev/null +++ b/kttsd/plugins/freetts/freettsproc.cpp @@ -0,0 +1,275 @@ +/**************************************************************************** + Main speaking functions for the FreeTTS Plug in + ------------------- + Copyright : (C) 2004 Paul Giannaros + ------------------- + Original author: Paul Giannaros <ceruleanblaze@gmail.com> + Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com> + ******************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include <qstring.h> +#include <qstringlist.h> +#include <qfileinfo.h> + +#include <kdebug.h> +#include <kconfig.h> +#include <kstandarddirs.h> +#include <kprocess.h> + +#include "freettsproc.h" + +/** Constructor */ +FreeTTSProc::FreeTTSProc( QObject* parent, const char* name, const QStringList& /*args*/) : + PlugInProc( parent, name ) { + kdDebug() << "Running: FreeTTSProc::FreeTTSProc" << endl; + m_state = psIdle; + m_waitingStop = false; + m_freettsProc = 0; +} + +/** Desctructor */ +FreeTTSProc::~FreeTTSProc() { + kdDebug() << "Running: FreeTTSProc::~FreeTTSProc" << endl; + if (m_freettsProc) { + stopText(); + delete m_freettsProc; + } +} + +/** Initializate the speech */ +bool FreeTTSProc::init(KConfig *config, const QString &configGroup) { + kdDebug() << "Running: FreeTTSProc::init()" << endl; + kdDebug() << "Initializing plug in: FreeTTS" << endl; + config->setGroup(configGroup); + m_freettsJarPath = config->readEntry("FreeTTSJarPath", "freetts.jar"); + kdDebug() << "FreeTTSProc::init: path to freetts.jar: " << m_freettsJarPath << endl; + return true; +} + +/** + * Say a text. Synthesize and audibilize it. + * @param text The text to be spoken. + * + * If the plugin supports asynchronous operation, it should return immediately. + */ +void FreeTTSProc::sayText(const QString &text) { + synth(text, QString::null, m_freettsJarPath); +} + +/** + * 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. + */ +void FreeTTSProc::synthText(const QString& text, const QString& suggestedFilename) { + kdDebug() << "Running: FreeTTSProc::synthText" << endl; + synth(text, suggestedFilename, m_freettsJarPath); +} + +// A little helper function because KDE 3.2 kdDebug() does not support QValueList<QCString>. +QStringList argsToQStringList(const QValueList<QCString> list) +{ + QStringList newList; + QValueList<QCString>::ConstIterator it = list.begin(); + for ( ; it != list.end(); ++it ) newList.append(*it); + return newList; +} + +void FreeTTSProc::synth( + const QString &text, + const QString &synthFilename, + const QString& freettsJarPath) { + + kdDebug() << "Running: FreeTTSProc::synth" << endl; + + if (m_freettsProc) { + if (m_freettsProc->isRunning()) m_freettsProc->kill(); + delete m_freettsProc; + m_freettsProc = 0; + + } + + m_freettsProc = new KProcess; + connect(m_freettsProc, SIGNAL(processExited(KProcess*)), + this, SLOT(slotProcessExited(KProcess*))); + connect(m_freettsProc, SIGNAL(receivedStdout(KProcess*, char*, int)), + this, SLOT(slotReceivedStdout(KProcess*, char*, int))); + connect(m_freettsProc, SIGNAL(receivedStderr(KProcess*, char*, int)), + this, SLOT(slotReceivedStderr(KProcess*, char*, int))); + connect(m_freettsProc, SIGNAL(wroteStdin(KProcess*)), + this, SLOT(slotWroteStdin(KProcess* ))); + if (synthFilename.isNull()) + m_state = psSaying; + else + m_state = psSynthing; + + + QString saidText = text; + saidText += "\n"; + + /// As freetts.jar doesn't seem to like being called from an absolute path, + /// we need to strip off the path to freetts.jar and pass it to + /// KProcess::setWorkingDirectory() + /// We could just strip off 11 characters from the end of the path to freetts.jar, but thats + /// not exactly very portable... + QString filename = QFileInfo(freettsJarPath).baseName().append(QString(".").append(QFileInfo(freettsJarPath).extension())); + QString freettsJarDir = freettsJarPath.left((freettsJarPath.length() - filename.length()) - 1); + + m_freettsProc->setWorkingDirectory(freettsJarDir); + kdDebug() << "FreeTTSProc::synthText: moved to directory '" << freettsJarDir << "'" << endl; + kdDebug() << "FreeTTSProc::synthText: Running file: '" << filename << "'" << endl; + *m_freettsProc << "java" << "-jar" << filename; + + /// Dump audio into synthFilename + + if (!synthFilename.isNull()) *m_freettsProc << "-dumpAudio" << synthFilename; + + m_synthFilename = synthFilename; + + kdDebug() << "FreeTTSProc::synth: Synthing text: '" << saidText << "' using FreeTTS plug in" << endl; + if (!m_freettsProc->start(KProcess::NotifyOnExit, KProcess::All)) { + kdDebug() << "FreeTTSProc::synth: Error starting FreeTTS process. Is freetts.jar in the PATH?" << endl; + m_state = psIdle; + kdDebug() << "KProcess args: " << argsToQStringList(m_freettsProc->args()) << endl; + return; + } + kdDebug()<< "FreeTTSProc:synth: FreeTTS initialized" << endl; + m_freettsProc->writeStdin(saidText.latin1(), saidText.length()); +} + +/** + * Returning the filename of the synth'd text + * @returns The filename of the last synth'd text + */ +QString FreeTTSProc::getFilename() { + kdDebug() << "FreeTTSProc::getFilename: returning " << m_synthFilename << endl; + return m_synthFilename; +} + +/** + * 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. + */ +void FreeTTSProc::stopText() { + kdDebug() << "FreeTTSProc::stopText:: Running" << endl; + if (m_freettsProc) { + if (m_freettsProc->isRunning()) { + kdDebug() << "FreeTTSProc::stopText: killing FreeTTS." << endl; + m_waitingStop = true; + m_freettsProc->kill(); + } + else m_state = psIdle; + } + else m_state = psIdle; + kdDebug() << "FreeTTSProc::stopText: FreeTTS stopped." << endl; +} + +void FreeTTSProc::slotProcessExited(KProcess*) { + kdDebug() << "FreeTTSProc:slotProcessExited: FreeTTS process has exited." << endl; + pluginState prevState = m_state; + if (m_waitingStop) { + m_waitingStop = false; + m_state = psIdle; + emit stopped(); + } + else { + m_state = psFinished; + if (prevState == psSaying) + emit sayFinished(); + else if (prevState == psSynthing) + emit synthFinished(); + } +} + +void FreeTTSProc::slotReceivedStdout(KProcess*, char* buffer, int buflen) { + QString buf = QString::fromLatin1(buffer, buflen); + kdDebug() << "FreeTTSProc::slotReceivedStdout: Received output from FreeTTS: " << buf << endl; +} + +void FreeTTSProc::slotReceivedStderr(KProcess*, char* buffer, int buflen) { + QString buf = QString::fromLatin1(buffer, buflen); + kdDebug() << "FreeTTSProc::slotReceivedStderr: Received error from FreeTTS: " << buf << endl; +} + +void FreeTTSProc::slotWroteStdin(KProcess*) { + kdDebug() << "FreeTTSProc::slotWroteStdin: closing Stdin" << endl; + m_freettsProc->closeStdin(); +} + +/** + * Return the current state of the plugin. + * This function only makes sense in asynchronous mode. + * @return The pluginState of the plugin. + * + * @see pluginState + */ +pluginState FreeTTSProc::getState() { + return m_state; +} + +/** + * 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. + */ +void FreeTTSProc::ackFinished() { + if (m_state == psFinished) { + m_state = psIdle; + m_synthFilename = QString::null; + } +} + +/** + * 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. + */ +bool FreeTTSProc::supportsAsync() { +// return true; + return true; +} + +/** + * 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. + */ +bool FreeTTSProc::supportsSynth() { +// return true; + return true; +} + + +#include "freettsproc.moc" diff --git a/kttsd/plugins/freetts/freettsproc.h b/kttsd/plugins/freetts/freettsproc.h new file mode 100644 index 0000000..b2bb631 --- /dev/null +++ b/kttsd/plugins/freetts/freettsproc.h @@ -0,0 +1,180 @@ +/**************************************************************************** + Main speaking functions for the FreeTTS Plug in + ------------------- + Copyright : (C) 2004 Paul Giannaros + ------------------- + Original author: Paul Giannaros <ceruleanblaze@gmail.com> + Current Maintainer: Paul Giannaros <ceruleanblaze@gmail.com> + ******************************************************************************/ + +/*************************************************************************** + * * + * 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 _FREETTSPROC_H_ +#define _FREETTSPROC_H_ + + +#include <qstringlist.h> +#include <qmutex.h> + +#include <pluginproc.h> + +class KProcess; + +class FreeTTSProc : public PlugInProc{ + Q_OBJECT + +public: + /** + * Constructor + */ + FreeTTSProc( QObject* parent = 0, const char* name = 0, const QStringList &args = QStringList()); + + /** + * Destructor + */ + virtual ~FreeTTSProc(); + + /** + * Initializate the speech engine. + * @param config Settings object. + * @param configGroup Settings group. + */ + virtual bool init(KConfig *config, const QString &configGroup); + + /** + * Say a text string. + * @param text The text to speak. + */ + 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. + */ + virtual void synthText(const QString& text, const QString& suggestedFilename); + + /** + * Get the generated audio filename from synthText. + * @return Name of the audio file the plugin generated. + * Null if no such file. + * + * The plugin must not re-use the filename. + */ + 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. + */ + virtual bool supportsSynth(); + + /** + * Say or Synthesize text. + * @param text The text to be synthesized. + * @param synthFilename If not Null, synthesize only to this filename, otherwise + * synthesize and audibilize the text. + * @param freettsJarPath Path to the freetts jar file. + */ + void synth( + const QString &text, + const QString &synthFilename, + const QString &freettsJarPath); + +private slots: + void slotProcessExited(KProcess* proc); + void slotReceivedStdout(KProcess* proc, char* buffer, int buflen); + void slotReceivedStderr(KProcess* proc, char* buffer, int buflen); + void slotWroteStdin(KProcess* proc); + +private: + + /** + * Path to FreeTTS jar file (from config). + */ + QString m_freettsJarPath; + + /** + * FreeTTS process + */ + KProcess* m_freettsProc; + + /** + * Synthesis filename. + */ + QString m_synthFilename; + + /** + * Plugin state. + */ + pluginState m_state; + + /** + * True when stopText has been called. Used to force transition to psIdle when + * FreeTTS exits. + */ + bool m_waitingStop; + +}; + +#endif // _FREETTSPROC_H_ diff --git a/kttsd/plugins/freetts/kttsd_freettsplugin.desktop b/kttsd/plugins/freetts/kttsd_freettsplugin.desktop new file mode 100644 index 0000000..cdfab63 --- /dev/null +++ b/kttsd/plugins/freetts/kttsd_freettsplugin.desktop @@ -0,0 +1,51 @@ +[Desktop Entry] +Name=FreeTTS +Name[tr]=Freetts +Name[vi]=Văn bản sang Tiếng nói Tự do +Comment=FreeTTS speech synthesizer +Comment[bg]=Синтезатор на глас FreeTTS +Comment[ca]=Sintetitzador de veu FreeTTS +Comment[cs]=Hlasový syntetizér FreeTTS +Comment[da]=FreeTTS tale-synthesizer +Comment[de]=FreeTTS Sprachsynthesizer +Comment[el]=Συνθέτης ομιλίας FreeTTS +Comment[es]=Sintetizador de texto a voz FreeTTS +Comment[et]=Kõnesüntesaator FreeTTS +Comment[eu]=FreeTTS hizketa-sintetizadorea +Comment[fa]=ترکیبدهندۀ گفتار FreeTTS +Comment[fi]=FreeTTS puhesyntetisaattori +Comment[fr]=Synthèse vocale FreeTTS +Comment[ga]=Sintéiseoir cainte FreeTTS +Comment[gl]=Sintetizador de voces FreeTTS +Comment[hu]=FreeTTS beszédszintetizátor +Comment[is]=FreeTTS talgerfill +Comment[it]=Sintetizzatore vocale FreeTTS +Comment[ja]=FreeTTS スピーチシンセサイザ +Comment[ka]=FreeTTS ხმის სინთეზატორი +Comment[km]=កម្មវិធីសង្គ្រោះការនិយាយ FreeTTS +Comment[mk]=FreeTTS синтетизатор на говор +Comment[ms]=Pensintesis tutur FreeTTS +Comment[nb]=FreeTTS talesyntetisering +Comment[nds]=Blicksnuut FreeTTS +Comment[ne]=FreeTTS संवाद सिन्थेसाइजर +Comment[nl]=FreeTTS spraaksynthesizer +Comment[pa]=FreeTTS ਬੋਲੀ ਸੰਸਲੇਸ਼ਕ +Comment[pl]=Syntezator mowy FreeTTS +Comment[pt]=O sintetizador de fala FreeTTS +Comment[pt_BR]=Sintetizador de fala FreeTTS +Comment[ru]=Синтезатор речи FreeTTS +Comment[sk]=Syntetizátor reči FreeTTS +Comment[sl]=Sintetizator govora FreeTTS +Comment[sr]=Синтетизатор говора FreeTTS +Comment[sr@Latn]=Sintetizator govora FreeTTS +Comment[sv]=FreeTTS talsyntes +Comment[ta]=FreeTTS பேச்சு கூட்டிணைப்பான் +Comment[tg]=Таҳлилгари овози FreeTTS +Comment[tr]=FreeTTS konuşma bireştirici +Comment[uk]=Синтезатор мовлення FreeTTS +Comment[vi]=Trình tổng hợp tiếng nói Tự do +Comment[zh_TW]=FreeTTS 語音合成器 +Type=Service +ServiceTypes=KTTSD/SynthPlugin +X-KDE-Library=libkttsd_freettsplugin +X-KDE-Languages=en,en_US,en_GB |