Fix include
[kdeaccessibility.git] / kttsd / plugins / hadifix / hadifixconf.cpp
blob1927b7cbe12489b1607312f1f58e2f27ef7e6a54
1 /***************************************************************************
2 begin : Mon Okt 14 2002
3 copyright : (C) 2002 by Gunnar Schmi Dt
4 email : gunnar@schmi-dt.de
5 current mainainer: : Gary Cramblitt <garycramblitt@comcast.net>
6 ***************************************************************************/
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
17 // System includes.
18 #include <math.h>
20 // Qt includes.
21 #include <QLayout>
22 #include <QLabel>
23 #include <QGroupBox>
25 #include <QDir>
26 #include <QFileInfo>
27 #include <QFile>
28 #include <QVBoxLayout>
29 #include <QTextStream>
31 // KDE includes.
32 #include <ktemporaryfile.h>
33 #include <kdebug.h>
34 #include <klocale.h>
35 #include <kdialog.h>
36 #include <kcombobox.h>
37 #include <kstandarddirs.h>
38 #include <kurlrequester.h>
39 #include <klineedit.h>
40 #include <knuminput.h>
41 #include <kprogressdialog.h>
42 #include <kicon.h>
44 // KTTS includes.
45 #include <pluginconf.h>
46 #include <testplayer.h>
47 #include <talkercode.h>
49 // Hadifix includes.
50 #include "hadifixproc.h"
51 #include "hadifixconf.h"
52 #include "hadifixconf.moc"
53 #include "ui_voicefileui.h"
55 // ====================================================================
56 // HadifixConfPrivate
58 HadifixConfPrivate::HadifixConfPrivate(QWidget *parent) :
59 QWidget(parent)
61 hadifixProc = 0;
62 progressDlg = 0;
63 setupUi(this);
64 findInitialConfig();
67 HadifixConfPrivate::~HadifixConfPrivate() {
68 if (hadifixProc) hadifixProc->stopText();
69 delete hadifixProc;
70 if (!waveFile.isNull()) QFile::remove(waveFile);
71 delete progressDlg;
74 // Basically the slider values are logarithmic (0,...,1000) whereas percent
75 // values are linear (50%,...,200%).
77 // slider = alpha * (log(percent)-log(50))
78 // with alpha = 1000/(log(200)-log(50))
80 int HadifixConfPrivate::percentToSlider (int percentValue) {
81 double alpha = 1000 / (log(200) - log(50));
82 return (int)floor (0.5 + alpha * (log(percentValue)-log(50)));
85 int HadifixConfPrivate::sliderToPercent (int sliderValue) {
86 double alpha = 1000 / (log(200) - log(50));
87 return (int)floor(0.5 + exp (sliderValue/alpha + log(50)));
90 void HadifixConfPrivate::volumeBox_valueChanged (int percentValue) {
91 volumeSlider->setValue (percentToSlider (percentValue));
94 void HadifixConfPrivate::timeBox_valueChanged (int percentValue) {
95 timeSlider->setValue (percentToSlider (percentValue));
98 void HadifixConfPrivate::frequencyBox_valueChanged (int percentValue) {
99 frequencySlider->setValue (percentToSlider (percentValue));
102 void HadifixConfPrivate::volumeSlider_valueChanged (int sliderValue) {
103 volumeBox->setValue (sliderToPercent (sliderValue));
106 void HadifixConfPrivate::timeSlider_valueChanged (int sliderValue) {
107 timeBox->setValue (sliderToPercent (sliderValue));
110 void HadifixConfPrivate::frequencySlider_valueChanged (int sliderValue) {
111 frequencyBox->setValue (sliderToPercent (sliderValue));
114 void HadifixConfPrivate::init () {
117 void HadifixConfPrivate::addVoice (const QString &filename, bool isMale) {
118 if (isMale) {
119 if (!maleVoices.contains(filename)) {
120 int id = voiceCombo->count();
121 maleVoices.insert (filename, id);
122 voiceCombo->addItem (KIcon("male"), filename);
125 else {
126 if (!femaleVoices.contains(filename)) {
127 int id = voiceCombo->count();
128 femaleVoices.insert (filename, id);
129 voiceCombo->addItem (KIcon("female"), filename);
134 void HadifixConfPrivate::addVoice (const QString &filename, bool isMale, const QString &displayname) {
135 addVoice (filename, isMale);
137 if (isMale) {
138 defaultVoicesMap [maleVoices [filename]] = filename;
139 voiceCombo->setItemIcon (maleVoices [filename], KIcon("male"));
140 voiceCombo->setItemText (maleVoices [filename], displayname);
142 else{
143 defaultVoicesMap [femaleVoices [filename]] = filename;
144 voiceCombo->setItemIcon (femaleVoices [filename], KIcon("female"));
145 voiceCombo->setItemText (femaleVoices [filename], displayname);
149 void HadifixConfPrivate::setVoice (const QString &filename, bool isMale) {
150 addVoice (filename, isMale);
151 if (isMale)
152 voiceCombo->setCurrentIndex (maleVoices[filename]);
153 else
154 voiceCombo->setCurrentIndex (femaleVoices[filename]);
157 QString HadifixConfPrivate::getVoiceFilename() {
158 int curr = voiceCombo->currentIndex();
160 QString filename = voiceCombo->itemText(curr);
161 if (defaultVoicesMap.contains(curr))
162 filename = defaultVoicesMap[curr];
164 return filename;
167 bool HadifixConfPrivate::isMaleVoice() {
168 int curr = voiceCombo->currentIndex();
169 QString filename = getVoiceFilename();
171 if (maleVoices.contains(filename))
172 return maleVoices[filename] == curr;
173 else
174 return false;
178 * Tries to find hadifix and mbrola by looking onto the hard disk. This is
179 * necessary because both hadifix and mbrola do not have standard
180 * installation directories.
182 void HadifixConfPrivate::findInitialConfig() {
183 QString hadifixDataPath = findHadifixDataPath();
185 defaultHadifixExec = findExecutable(QStringList("txt2pho"), hadifixDataPath+"/../");
187 QStringList list; list += "mbrola"; list += "mbrola-linux-i386";
188 defaultMbrolaExec = findExecutable(list, hadifixDataPath+"/../../mbrola/");
190 defaultVoices = findVoices (defaultMbrolaExec, hadifixDataPath);
193 /** Tries to find the hadifix data path by looking into a number of files. */
194 QString HadifixConfPrivate::findHadifixDataPath () {
195 QStringList files;
196 files += "/etc/txt2pho";
197 files += QDir::homePath()+"/.txt2phorc";
199 QStringList::iterator it;
200 for (it = files.begin(); it != files.end(); ++it) {
202 QFile file(*it);
203 if ( file.open(QIODevice::ReadOnly) ) {
204 QTextStream stream(&file);
206 while (!stream.atEnd()) {
207 QString s = stream.readLine().trimmed();
208 // look for a line "DATAPATH=..."
210 if (s.startsWith("DATAPATH")) {
211 s = s.mid(8, s.length()-8).trimmed();
212 if (s.startsWith("=")) {
213 s = s.mid(1, s.length()-1).trimmed();
214 if (s.startsWith("/"))
215 return s;
216 else {
217 QFileInfo info (QFileInfo(*it).path() + '/' + s);
218 return info.absoluteFilePath();
223 file.close();
226 return "/usr/local/txt2pho/";
229 /** Tries to find the an executable by looking onto the hard disk. */
230 QString HadifixConfPrivate::findExecutable (const QStringList &names, const QString &possiblePath) {
231 // a) Try to find it directly
232 QStringList::ConstIterator it;
233 QStringList::ConstIterator itEnd = names.constEnd();
234 for (it = names.constBegin(); it != itEnd; ++it) {
235 QString executable = KStandardDirs::findExe (*it);
236 if (!executable.isNull() && !executable.isEmpty())
237 return executable;
240 // b) Try to find it in the path specified by the second parameter
241 for (it = names.constBegin(); it != itEnd; ++it) {
242 QFileInfo info (possiblePath+*it);
243 if (info.exists() && info.isExecutable() && info.isFile()) {
244 return info.absoluteFilePath();
248 // Both tries failed, so the user has to locate the executable.
249 return QString();
252 /** Tries to find the voice files by looking onto the hard disk. */
253 QStringList HadifixConfPrivate::findVoices(QString mbrolaExec, const QString &hadifixDataPath) {
255 // First of all:
256 // dereference links to the mbrola executable (if mbrolaExec is a link).
257 for (int i = 0; i < 10; ++i) {
258 // If we have a chain of more than ten links something is surely wrong.
259 QFileInfo info (mbrolaExec);
260 if (info.exists() && info.isSymLink())
261 mbrolaExec = info.readLink();
264 // Second:
265 // create a list of directories that possibly contain voice files
266 QStringList list;
268 // 2a) search near the mbrola executable
269 QFileInfo info (mbrolaExec);
270 if (info.exists() && info.isFile() && info.isExecutable()) {
271 QString mbrolaPath = info.absolutePath();
272 list += mbrolaPath;
275 // 2b) search near the hadifix data path
276 info.setFile(hadifixDataPath + "../../mbrola");
277 QString mbrolaPath = info.absolutePath() + "/mbrola";
278 if (!list.contains(mbrolaPath))
279 list += mbrolaPath;
281 // 2c) broaden the search by adding subdirs (with a depth of 2)
282 QStringList subDirs = findSubdirs (list);
283 QStringList subSubDirs = findSubdirs (subDirs);
284 list += subDirs;
285 list += subSubDirs;
287 // Third:
288 // look into each of these directories and search for voice files.
289 QStringList result;
290 QStringList::iterator it;
291 for (it = list.begin(); it != list.end(); ++it) {
292 QDir baseDir (*it, QString(),
293 QDir::Name|QDir::IgnoreCase, QDir::Files);
294 QStringList files = baseDir.entryList();
296 QStringList::iterator iter;
297 for (iter = files.begin(); iter != files.end(); ++iter) {
298 // Voice files start with "MBROLA", but are afterwards binary files
299 QString filename = *it + '/' + *iter;
300 QFile file (filename);
301 if (file.open(QIODevice::ReadOnly)) {
302 QTextStream stream(&file);
303 if (!stream.atEnd()) {
304 QString s = stream.readLine();
305 if (s.startsWith("MBROLA"))
306 if (HadifixProc::determineGender(mbrolaExec, filename)
307 != HadifixProc::NoVoice)
308 result += filename;
309 file.close();
314 return result;
317 /** Returns a list of subdirs (with absolute paths) */
318 QStringList HadifixConfPrivate::findSubdirs (const QStringList &baseDirs) {
319 QStringList result;
321 QStringList::ConstIterator it;
322 QStringList::ConstIterator itEnd = baseDirs.constEnd();
323 for (it = baseDirs.constBegin(); it != itEnd; ++it) {
324 // a) get a list of directory names
325 QDir baseDir (*it, QString(),
326 QDir::Name|QDir::IgnoreCase, QDir::Dirs);
327 QStringList list = baseDir.entryList();
329 // b) produce absolute paths
330 QStringList::ConstIterator iter;
331 QStringList::ConstIterator iterEnd = list.constEnd();
332 for (iter = list.constBegin(); iter != iterEnd; ++iter) {
333 if ((*iter != ".") && (*iter != ".."))
334 result += *it + '/' + *iter;
337 return result;
340 void HadifixConfPrivate::setConfiguration (QString hadifixExec, QString mbrolaExec,
341 QString voice, bool male,
342 int volume, int time, int pitch,
343 QString codecName)
345 hadifixURL->setUrl (KUrl(hadifixExec));
346 mbrolaURL->setUrl (KUrl(mbrolaExec));
347 setVoice (voice, male);
349 volumeBox->setValue (volume);
350 timeBox->setValue (time);
351 frequencyBox->setValue (pitch);
352 int codec = PlugInProc::codecNameToListIndex(codecName, codecList);
353 characterCodingBox->setCurrentIndex(codec);
356 void HadifixConfPrivate::initializeVoices () {
357 QStringList::iterator it;
358 for (it = defaultVoices.begin(); it != defaultVoices.end(); ++it) {
359 HadifixProc::VoiceGender gender;
360 QString name = QFileInfo(*it).fileName();
361 gender = HadifixProc::determineGender(defaultMbrolaExec, *it);
362 if (gender == HadifixProc::MaleGender)
363 addVoice(*it, true, i18n("Male voice \"%1\"", name));
364 else if (gender == HadifixProc::FemaleGender)
365 addVoice(*it, false, i18n("Female voice \"%1\"", name));
366 else {
367 if (name == "de1")
368 addVoice(*it, false, i18n("Female voice \"%1\"", name));
369 else {
370 addVoice(*it, true, i18n("Unknown voice \"%1\"", name));
371 addVoice(*it, false, i18n("Unknown voice \"%1\"", name));
377 void HadifixConfPrivate::initializeCharacterCodes() {
378 // Build codec list and fill combobox.
379 codecList = PlugInProc::buildCodecList();
380 characterCodingBox->clear();
381 characterCodingBox->addItems(codecList);
384 void HadifixConfPrivate::setDefaultEncodingFromVoice() {
385 QString voiceFile = getVoiceFilename();
386 QString voiceCode = QFileInfo(voiceFile).baseName();
387 voiceCode = voiceCode.left(2);
388 QString codecName = "Local";
389 if (voiceCode == "de") codecName = "ISO 8859-1";
390 if (voiceCode == "hu") codecName = "ISO 8859-2";
391 characterCodingBox->setCurrentIndex(PlugInProc::codecNameToListIndex(
392 codecName, codecList));
395 void HadifixConfPrivate::setDefaults () {
396 QStringList::iterator it = defaultVoices.begin();
397 // Find a voice that matches language code, if any.
398 if (!languageCode.isEmpty())
400 QString justLang = languageCode.left(2);
401 for (;it != defaultVoices.end();++it)
403 QString voiceCode = QFileInfo(*it).baseName().left(2);
404 if (voiceCode == justLang) break;
406 if (it == defaultVoices.end()) it = defaultVoices.begin();
408 HadifixProc::VoiceGender gender;
409 gender = HadifixProc::determineGender(defaultMbrolaExec, *it);
411 setConfiguration (defaultHadifixExec, defaultMbrolaExec,
412 *it, gender == HadifixProc::MaleGender,
413 100, 100, 100, "Local");
416 void HadifixConfPrivate::load (KConfig *c, const QString &configGroup) {
417 KConfigGroup config(c, configGroup);
419 QString voice = config.readEntry("voice", getVoiceFilename());
421 HadifixProc::VoiceGender gender;
422 gender = HadifixProc::determineGender(defaultMbrolaExec, voice);
423 bool isMale = (gender == HadifixProc::MaleGender);
425 QString defaultCodecName = "Local";
426 // TODO: Need a better way to determine proper codec for each voice.
427 // This will do for now.
428 QString voiceCode = QFileInfo(voice).baseName();
429 if (voiceCode.left(2) == "de") defaultCodecName = "ISO 8859-1";
430 if (voiceCode.left(2) == "hu") defaultCodecName = "ISO 8859-2";
432 setConfiguration (
433 config.readEntry ("hadifixExec",defaultHadifixExec),
434 config.readEntry ("mbrolaExec", defaultMbrolaExec),
435 config.readEntry ("voice", voice),
436 config.readEntry("gender", isMale),
437 config.readEntry ("volume", 100),
438 config.readEntry ("time", 100),
439 config.readEntry ("pitch", 100),
440 config.readEntry ("codec", defaultCodecName)
444 void HadifixConfPrivate::save (KConfig *c, const QString &configGroup) {
445 KConfigGroup config(c, configGroup);
446 config.writeEntry ("hadifixExec", PlugInConf::realFilePath(hadifixURL->url().path()));
447 config.writeEntry ("mbrolaExec", PlugInConf::realFilePath(mbrolaURL->url().path()));
448 config.writeEntry ("voice", getVoiceFilename());
449 config.writeEntry ("gender", isMaleVoice());
450 config.writeEntry ("volume", volumeBox->value());
451 config.writeEntry ("time", timeBox->value());
452 config.writeEntry ("pitch", frequencyBox->value());
453 config.writeEntry ("codec", PlugInProc::codecIndexToCodecName(
454 characterCodingBox->currentIndex(), codecList));
457 // ====================================================================
458 // HadifixConf
460 /** Constructor */
461 HadifixConf::HadifixConf( QWidget* parent, const QStringList &) :
462 PlugInConf( parent, "hadifixconf" ){
463 // kDebug() << "HadifixConf::HadifixConf: Running" << endl;
464 QVBoxLayout *layout = new QVBoxLayout (this);
465 layout->setAlignment (Qt::AlignTop);
467 d = new HadifixConfPrivate(parent);
469 // QString file = locate("data", "LICENSES/LGPL_V2");
470 i18n("This plugin is distributed under the terms of the GPL v2 or later.");
472 connect(d->voiceButton, SIGNAL(clicked()), this, SLOT(voiceButton_clicked()));
473 connect(d->testButton, SIGNAL(clicked()), this, SLOT(testButton_clicked()));
474 connect(d->voiceCombo, SIGNAL(activated(int)), this, SLOT(voiceCombo_activated(int)));
475 connect(d->volumeBox, SIGNAL(valueChanged(int)), d, SLOT(volumeBox_valueChanged(int)));
476 connect(d->volumeSlider, SIGNAL(valueChanged(int)), d, SLOT(volumeSlider_valueChanged(int)));
477 connect(d->timeBox, SIGNAL(valueChanged(int)), d, SLOT(timeBox_valueChanged(int)));
478 connect(d->timeSlider, SIGNAL(valueChanged(int)), d, SLOT(timeSlider_valueChanged(int)));
479 connect(d->frequencyBox, SIGNAL(valueChanged(int)), d, SLOT(frequencyBox_valueChanged(int)));
480 connect(d->frequencySlider, SIGNAL(valueChanged(int)), d, SLOT(frequencySlider_valueChanged(int)));
482 connect(d->characterCodingBox, SIGNAL(textChanged(const QString&)), this, SLOT(configChanged()));
483 connect(d->voiceCombo, SIGNAL(activated(const QString)), this, SLOT(configChanged()));
484 connect(d->voiceCombo, SIGNAL(activated(const QString)), this, SLOT(configChanged()));
485 connect(d->volumeBox, SIGNAL(valueChanged(const QString)), this, SLOT(configChanged()));
486 connect(d->timeBox, SIGNAL(valueChanged(const QString)), this, SLOT(configChanged()));
487 connect(d->frequencyBox, SIGNAL(valueChanged(const QString)), this, SLOT(configChanged()));
488 connect(d->hadifixURL, SIGNAL(textChanged(const QString)), this, SLOT(configChanged()));
489 connect(d->mbrolaURL, SIGNAL(textChanged(const QString)), this, SLOT(configChanged()));
491 d->initializeCharacterCodes();
492 d->initializeVoices();
493 d->setDefaults();
494 layout->addWidget (d);
497 /** Destructor */
498 HadifixConf::~HadifixConf(){
499 // kDebug() << "HadifixConf::~HadifixConf: Running" << endl;
500 delete d;
503 void HadifixConf::load(KConfig *config, const QString &configGroup) {
504 // kDebug() << "HadifixConf::load: Running" << endl;
505 d->setDefaults();
506 d->load (config, configGroup);
509 void HadifixConf::save(KConfig *config, const QString &configGroup) {
510 // kDebug() << "HadifixConf::save: Running" << endl;
511 d->save (config, configGroup);
514 void HadifixConf::defaults() {
515 // kDebug() << "HadifixConf::defaults: Running" << endl;
516 d->setDefaults();
519 void HadifixConf::setDesiredLanguage(const QString &lang)
521 d->languageCode = lang;
524 QString HadifixConf::getTalkerCode()
526 if (!d->hadifixURL->url().path().isEmpty() && !d->mbrolaURL->url().path().isEmpty())
528 QString voiceFile = d->getVoiceFilename();
529 if (QFileInfo(voiceFile).exists())
531 // mbrola voice file names usually start with two-letter language code,
532 // but this is by no means guaranteed.
533 QString voiceCode = QFileInfo(voiceFile).baseName();
534 QString voiceLangCode = voiceCode.left(2);
535 if (d->languageCode.left(2) != voiceLangCode)
537 // Verify that first two letters of voice filename are a valid language code.
538 // If they are, switch to that language.
539 if (!TalkerCode::languageCodeToLanguage(voiceLangCode).isEmpty())
540 d->languageCode = voiceLangCode;
542 QString gender = "male";
543 if (!d->isMaleVoice()) gender = "female";
544 QString volume = "medium";
545 if (d->volumeBox->value() < 75) volume = "soft";
546 if (d->volumeBox->value() > 125) volume = "loud";
547 QString rate = "medium";
548 if (d->timeBox->value() < 75) rate = "slow";
549 if (d->timeBox->value() > 125) rate = "fast";
550 return QString(
551 "<voice lang=\"%1\" name=\"%2\" gender=\"%3\" />"
552 "<prosody volume=\"%4\" rate=\"%5\" />"
553 "<kttsd synthesizer=\"%6\" />")
554 .arg(d->languageCode)
555 .arg(voiceCode)
556 .arg(gender)
557 .arg(volume)
558 .arg(rate)
559 .arg("Hadifix");
562 return QString();
565 void HadifixConf::voiceButton_clicked () {
566 KDialog *dialog = new KDialog (this);
567 dialog->setCaption(i18n("Voice File - Hadifix Plugin"));
568 dialog->setButtons(KDialog::Ok|KDialog::Cancel);
569 // TODO: Workaround for KDialog bug. Remove when no longer needed.
570 dialog->setDefaultButton(KDialog::Cancel);
572 QWidget *w = new QWidget(dialog);
573 Ui::VoiceFileWidget voicefile;
574 voicefile.setupUi(w);
575 dialog->setMainWidget(w);
577 voicefile.femaleOption->setChecked(!d->isMaleVoice());
578 voicefile.maleOption->setChecked(d->isMaleVoice());
579 voicefile.voiceFileURL->setUrl(KUrl::fromPath(d->getVoiceFilename()));
581 if (dialog->exec() == QDialog::Accepted) {
582 d->setVoice (voicefile.voiceFileURL->url().path(), voicefile.maleOption->isChecked());
583 d->setDefaultEncodingFromVoice();
584 emit changed(true);
587 delete dialog;
590 void HadifixConf::voiceCombo_activated(int /*index*/)
592 d->setDefaultEncodingFromVoice();
595 void HadifixConf::testButton_clicked () {
596 // If currently synthesizing, stop it.
597 if (d->hadifixProc)
598 d->hadifixProc->stopText();
599 else
601 d->hadifixProc = new HadifixProc();
602 connect (d->hadifixProc, SIGNAL(stopped()), this, SLOT(slotSynthStopped()));
604 // Create a temp file name for the wave file.
605 KTemporaryFile tempFile;
606 tempFile.setPrefix("hadifixplugin-");
607 tempFile.setSuffix(".wav");
608 tempFile.setAutoRemove(false);
609 tempFile.open();
610 QString tmpWaveFile = tempFile.fileName();
612 // Tell user to wait.
613 d->progressDlg = new KProgressDialog(d,
614 i18n("Testing"),
615 i18n("Testing."));
616 d->progressDlg->setModal(true);
617 d->progressDlg->progressBar()->hide();
618 d->progressDlg->setAllowCancel(true);
620 // Speak a German sentence as hadifix is a German tts
621 // TODO: Actually, Hadifix does support English (and other languages?) as well,
622 // If you install the right voice files. The hard part is finding and installing
623 // a working txt2pho for the desired language. There seem to be some primitive french,
624 // italian, and a few others, written in perl, but they have many issues.
625 // Go to the mbrola website and click on "TTS" to learn more.
627 // QString testMsg = "K D E ist eine moderne grafische Arbeitsumgebung für UNIX-Computer.";
628 QString testMsg = testMessage(d->languageCode);
629 connect (d->hadifixProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
630 d->hadifixProc->synth (testMsg,
631 realFilePath(d->hadifixURL->url().path()),
632 d->isMaleVoice(),
633 realFilePath(d->mbrolaURL->url().path()),
634 d->getVoiceFilename(),
635 d->volumeBox->value(),
636 d->timeBox->value(),
637 d->frequencyBox->value(),
638 PlugInProc::codecIndexToCodec(d->characterCodingBox->currentIndex(), d->codecList),
639 tmpWaveFile);
641 // Display progress dialog modally. Processing continues when plugin signals synthFinished,
642 // or if user clicks Cancel button.
643 d->progressDlg->exec();
644 disconnect (d->hadifixProc, SIGNAL(synthFinished()), this, SLOT(slotSynthFinished()));
645 if (d->progressDlg->wasCancelled()) d->hadifixProc->stopText();
646 delete d->progressDlg;
647 d->progressDlg = 0;
650 void HadifixConf::slotSynthFinished()
652 // If user canceled, progress dialog is gone, so exit.
653 if (!d->progressDlg)
655 d->hadifixProc->ackFinished();
656 return;
658 // Hide the Cancel button so user can't cancel in the middle of playback.
659 d->progressDlg->showCancelButton(false);
660 // Get new wavefile name.
661 d->waveFile = d->hadifixProc->getFilename();
662 // Tell synth we're done.
663 d->hadifixProc->ackFinished();
664 // Play the wave file (possibly adjusting its Speed).
665 // Player object deletes the wave file when done.
666 if (m_player) m_player->play(d->waveFile);
667 QFile::remove(d->waveFile);
668 d->waveFile.clear();
669 if (d->progressDlg) d->progressDlg->close();
672 void HadifixConf::slotSynthStopped()
674 // Clean up after canceling test.
675 QString filename = d->hadifixProc->getFilename();
676 // kDebug() << "HadifixConf::slotSynthStopped: filename = " << filename << endl;
677 if (!filename.isNull()) QFile::remove(filename);