more krazy fixes (include own header first, and missing e-mail addresses
[kdeaccessibility.git] / kttsd / plugins / epos / eposconf.cpp
blob54bf780d72b03bc0200435420d23b1c53625569c
1 /***************************************************** vim:set ts=4 sw=4 sts=4:
2 Configuration widget and functions for Epos 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 // Epos Plugin includes.
25 #include "eposconf.h"
26 #include "eposproc.h"
27 #include "eposconf.moc"
29 // C++ includes.
30 #include <math.h>
32 // Qt includes.
33 #include <QtCore/QFile>
34 #include <QtGui/QApplication>
35 #include <QtCore/QTextCodec>
36 #include <QtGui/QSlider>
38 // KDE includes.
39 #include <kdialog.h>
40 #include <ktemporaryfile.h>
41 #include <kstandarddirs.h>
42 #include <kcombobox.h>
43 #include <klocale.h>
44 #include <knuminput.h>
45 #include <kprogressdialog.h>
47 // KTTS includes.
48 #include <testplayer.h>
50 /** Constructor */
51 EposConf::EposConf( QWidget* parent, const QStringList& /*args*/) :
52 PlugInConf(parent, "eposconf")
54 // kDebug() << "EposConf::EposConf: Running";
55 m_eposProc = 0;
56 m_progressDlg = 0;
58 setupUi(this);
60 // Build codec list and fill combobox.
61 m_codecList = PlugInProc::buildCodecList();
62 characterCodingBox->clear();
63 characterCodingBox->addItems(m_codecList);
65 defaults();
67 connect(eposServerPath, SIGNAL(textChanged(const QString&)),
68 this, SLOT(configChanged()));
69 connect(eposClientPath, SIGNAL(textChanged(const QString&)),
70 this, SLOT(configChanged()));
71 connect(timeBox, SIGNAL(valueChanged(int)),
72 this, SLOT(timeBox_valueChanged(int)));
73 connect(frequencyBox, SIGNAL(valueChanged(int)),
74 this, SLOT(frequencyBox_valueChanged(int)));
75 connect(timeSlider, SIGNAL(valueChanged(int)),
76 this, SLOT(timeSlider_valueChanged(int)));
77 connect(frequencySlider, SIGNAL(valueChanged(int)),
78 this, SLOT(frequencySlider_valueChanged(int)));
79 connect(timeBox, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
80 connect(timeSlider, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
81 connect(frequencyBox, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
82 connect(frequencySlider, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
83 connect(characterCodingBox, SIGNAL(activated(const QString&)),
84 this, SLOT(configChanged()));
85 connect(eposServerOptions, SIGNAL(textChanged(const QString&)),
86 this, SLOT(configChanged()));
87 connect(eposClientOptions, SIGNAL(textChanged(const QString&)),
88 this, SLOT(configChanged()));
89 connect(eposTest, SIGNAL(clicked()),
90 this, SLOT(slotEposTest_clicked()));
93 /** Destructor */
94 EposConf::~EposConf(){
95 // kDebug() << "Running: EposConf::~EposConf()";
96 if (!m_waveFile.isNull()) QFile::remove(m_waveFile);
97 delete m_eposProc;
98 delete m_progressDlg;
101 void EposConf::load(KConfig *c, const QString &configGroup){
102 // kDebug() << "EposConf::load: Running ";
104 KConfigGroup config(c, configGroup);
105 eposServerPath->setUrl(KUrl::fromPath(config.readEntry("EposServerExePath", "epos")));
106 eposClientPath->setUrl(KUrl::fromPath(config.readEntry("EposClientExePath", "say")));
107 eposServerOptions->setText(config.readEntry("EposServerOptions", ""));
108 eposClientOptions->setText(config.readEntry("EposClientOptions", ""));
109 QString codecString = config.readEntry("Codec", "ISO 8859-2");
110 int codec = PlugInProc::codecNameToListIndex(codecString, m_codecList);
111 timeBox->setValue(config.readEntry("time", 100));
112 frequencyBox->setValue(config.readEntry("pitch", 100));
113 characterCodingBox->setCurrentIndex(codec);
117 * Converts a language code into the language setting passed to Epos synth.
119 QString EposConf::languageCodeToEposLanguage(const QString &languageCode)
121 QString eposLanguage;
122 if (languageCode.left(2) == "cs") eposLanguage = "czech";
123 if (languageCode.left(2) == "sk") eposLanguage = "slovak";
124 return eposLanguage;
127 void EposConf::save(KConfig *c, const QString &configGroup){
128 // kDebug() << "EposConf::save: Running";
131 KConfigGroup config(c, "Epos");
132 config.writeEntry("EposServerExePath",
133 realFilePath(eposServerPath->url().path()));
134 config.writeEntry("EposClientExePath",
135 realFilePath(eposClientPath->url().path()));
136 config.writeEntry("Language", languageCodeToEposLanguage(m_languageCode));
139 KConfigGroup config(c, configGroup);
140 config.writeEntry("EposServerExePath",
141 realFilePath(eposServerPath->url().path()));
142 config.writeEntry("EposClientExePath",
143 realFilePath(eposClientPath->url().path()));
144 config.writeEntry("EposServerOptions", eposServerOptions->text());
145 config.writeEntry("EposClientOptions", eposClientOptions->text());
146 config.writeEntry("time", timeBox->value());
147 config.writeEntry("pitch", frequencyBox->value());
148 int codec = characterCodingBox->currentIndex();
149 config.writeEntry("Codec", PlugInProc::codecIndexToCodecName(codec, m_codecList));
152 void EposConf::defaults(){
153 // kDebug() << "EposConf::defaults: Running";
154 eposServerPath->setUrl(KUrl("epos"));
155 eposClientPath->setUrl(KUrl("say"));
156 eposServerOptions->setText("");
157 eposClientOptions->setText("");
158 timeBox->setValue(100);
159 timeBox_valueChanged(100);
160 frequencyBox->setValue(100);
161 frequencyBox_valueChanged(100);
162 int codec = PlugInProc::codecNameToListIndex("ISO 8859-2", m_codecList);
163 characterCodingBox->setCurrentIndex(codec);
166 void EposConf::setDesiredLanguage(const QString &lang)
168 m_languageCode = lang;
171 QString EposConf::getTalkerCode()
173 QString eposServerExe = realFilePath(eposServerPath->url().path());
174 QString eposClientExe = realFilePath(eposClientPath->url().path());
175 if (!eposServerExe.isEmpty() && !eposClientExe.isEmpty())
177 if (!getLocation(eposServerExe).isEmpty() && !getLocation(eposClientExe).isEmpty())
179 QString rate = "medium";
180 if (timeBox->value() < 75) rate = "slow";
181 if (timeBox->value() > 125) rate = "fast";
182 return QString(
183 "<voice lang=\"%1\" name=\"%2\" gender=\"%3\" />"
184 "<prosody volume=\"%4\" rate=\"%5\" />"
185 "<kttsd synthesizer=\"%6\" />")
186 .arg(m_languageCode)
187 .arg("fixed")
188 .arg("neutral")
189 .arg("medium")
190 .arg(rate)
191 .arg("Epos TTS Synthesis System");
194 return QString();
197 void EposConf::slotEposTest_clicked()
199 // kDebug() << "EposConf::slotEposTest_clicked(): Running";
200 // If currently synthesizing, stop it.
201 if (m_eposProc)
202 m_eposProc->stopText();
203 else
205 m_eposProc = new EposProc();
206 connect (m_eposProc, SIGNAL(stopped()), this, SLOT(slotSynthStopped()));
208 // Create a temp file name for the wave file.
209 KTemporaryFile tempFile;
210 tempFile.setPrefix("eposplugin-");
211 tempFile.setSuffix(".wav");
212 tempFile.setAutoRemove(false);
213 tempFile.open();
214 QString tmpWaveFile = tempFile.fileName();
216 // Get test message in the language of the voice.
217 QString testMsg = testMessage(m_languageCode);
219 // Tell user to wait.
220 m_progressDlg = new KProgressDialog(this,
221 i18n("Testing"),
222 i18n("Testing."));
223 m_progressDlg->setModal(true);
224 m_progressDlg->progressBar()->hide();
225 m_progressDlg->setAllowCancel(true);
227 // TODO: Whenever server options change, the server must be restarted.
228 // TODO: Do codec names contain non-ASCII characters?
229 connect (m_eposProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
230 m_eposProc->synth(
231 testMsg,
232 tmpWaveFile,
233 realFilePath(eposServerPath->url().path()),
234 realFilePath(eposClientPath->url().path()),
235 eposServerOptions->text(),
236 eposClientOptions->text(),
237 PlugInProc::codecIndexToCodec(characterCodingBox->currentIndex(), m_codecList),
238 languageCodeToEposLanguage(m_languageCode),
239 timeBox->value(),
240 frequencyBox->value()
243 // Display progress dialog modally. Processing continues when plugin signals synthFinished,
244 // or if user clicks Cancel button.
245 m_progressDlg->exec();
246 disconnect (m_eposProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
247 if (m_progressDlg->wasCancelled()) m_eposProc->stopText();
248 delete m_progressDlg;
249 m_progressDlg = 0;
252 void EposConf::slotSynthFinished()
254 // If user canceled, progress dialog is gone, so exit.
255 if (!m_progressDlg)
257 m_eposProc->ackFinished();
258 return;
260 // Hide the Cancel button so user can't cancel in the middle of playback.
261 m_progressDlg->showCancelButton(false);
262 // Get new wavefile name.
263 m_waveFile = m_eposProc->getFilename();
264 // Tell synth we're done.
265 m_eposProc->ackFinished();
266 // Play the wave file (possibly adjusting its Speed).
267 // Player object deletes the wave file when done.
268 if (m_player) m_player->play(m_waveFile);
269 QFile::remove(m_waveFile);
270 m_waveFile.clear();
271 if (m_progressDlg) m_progressDlg->close();
274 void EposConf::slotSynthStopped()
276 // Clean up after canceling test.
277 QString filename = m_eposProc->getFilename();
278 if (!filename.isNull()) QFile::remove(filename);
281 // Basically the slider values are logarithmic (0,...,1000) whereas percent
282 // values are linear (50%,...,200%).
284 // slider = alpha * (log(percent)-log(50))
285 // with alpha = 1000/(log(200)-log(50))
287 int EposConf::percentToSlider(int percentValue) {
288 double alpha = 1000 / (log(200.0) - log(50.0));
289 return (int)floor (0.5 + alpha * (log((double)percentValue)-log(50.0L)));
292 int EposConf::sliderToPercent(int sliderValue) {
293 double alpha = 1000 / (log(200.0) - log(50.0));
294 return (int)floor(0.5 + exp (sliderValue/alpha + log(50.0)));
297 void EposConf::timeBox_valueChanged(int percentValue) {
298 timeSlider->setValue (percentToSlider (percentValue));
301 void EposConf::frequencyBox_valueChanged(int percentValue) {
302 frequencySlider->setValue(percentToSlider(percentValue));
305 void EposConf::timeSlider_valueChanged(int sliderValue) {
306 timeBox->setValue (sliderToPercent (sliderValue));
309 void EposConf::frequencySlider_valueChanged(int sliderValue) {
310 frequencyBox->setValue(sliderToPercent(sliderValue));