Oops. Only build mpegplayer bitmaps for SWCODEC.
[Rockbox.git] / rbutil / rbutilqt / tts.cpp
blobde8e1d446893493612077060b85acf1ea8446a57
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2007 by Dominik Wenger
10 * $Id: tts.cpp 15212 2007-10-19 21:49:07Z domonoky $
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include "tts.h"
22 #include "browsedirtree.h"
24 static QMap<QString,QString> ttsList;
25 static QMap<QString,TTSBase*> ttsCache;
27 void initTTSList()
29 ttsList["espeak"] = "Espeak TTS Engine";
30 ttsList["flite"] = "Flite TTS Engine";
31 ttsList["swift"] = "Swift TTS Engine";
32 #if defined(Q_OS_WIN)
33 ttsList["sapi"] = "Sapi 5 TTS Engine";
34 #endif
38 // function to get a specific encoder
39 TTSBase* getTTS(QString ttsname)
41 // init list if its empty
42 if(ttsList.count() == 0) initTTSList();
44 QString ttsName = ttsList.key(ttsname);
46 // check cache
47 if(ttsCache.contains(ttsName))
48 return ttsCache.value(ttsName);
50 TTSBase* tts;
51 if(ttsName == "sapi")
53 tts = new TTSSapi();
54 ttsCache[ttsName] = tts;
55 return tts;
57 else
59 tts = new TTSExes(ttsName);
60 ttsCache[ttsName] = tts;
61 return tts;
65 // get the list of encoders, nice names
66 QStringList getTTSList()
68 // init list if its empty
69 if(ttsList.count() == 0) initTTSList();
71 QStringList ttsNameList;
72 QMapIterator<QString, QString> i(ttsList);
73 while (i.hasNext()) {
74 i.next();
75 ttsNameList << i.value();
78 return ttsNameList;
82 /*********************************************************************
83 * TTS Base
84 **********************************************************************/
85 TTSBase::TTSBase(QWidget *parent): QDialog(parent)
90 /*********************************************************************
91 * General TTS Exes
92 **********************************************************************/
93 TTSExes::TTSExes(QString name,QWidget *parent) : TTSBase(parent)
95 m_name = name;
97 m_TemplateMap["espeak"] = "\"%exe\" \"%options\" -w \"%wavfile\" \"%text\"";
98 m_TemplateMap["flite"] = "\"%exe\" \"%options\" -o \"%wavfile\" \"%text\"";
99 m_TemplateMap["swift"] = "\"%exe\" \"%options\" -o \"%wavfile\" \"%text\"";
101 ui.setupUi(this);
102 this->hide();
103 connect(ui.reset,SIGNAL(clicked()),this,SLOT(reset()));
104 connect(ui.browse,SIGNAL(clicked()),this,SLOT(browse()));
107 bool TTSExes::start(QString *errStr)
109 userSettings->beginGroup(m_name);
110 m_TTSexec = userSettings->value("ttspath","").toString();
111 m_TTSOpts = userSettings->value("ttsoptions","").toString();
112 userSettings->endGroup();
114 m_TTSTemplate = m_TemplateMap.value(m_name);
116 QFileInfo tts(m_TTSexec);
117 if(tts.exists())
119 return true;
121 else
123 *errStr = tr("TTS executable not found");
124 return false;
128 bool TTSExes::voice(QString text,QString wavfile)
130 QString execstring = m_TTSTemplate;
132 execstring.replace("%exe",m_TTSexec);
133 execstring.replace("%options",m_TTSOpts);
134 execstring.replace("%wavfile",wavfile);
135 execstring.replace("%text",text);
136 //qDebug() << "voicing" << execstring;
137 QProcess::execute(execstring);
138 return true;
143 void TTSExes::reset()
145 ui.ttspath->setText("");
146 ui.ttsoptions->setText("");
149 void TTSExes::showCfg()
151 // try to get config from settings
152 userSettings->beginGroup(m_name);
153 QString exepath =userSettings->value("ttspath","").toString();
154 ui.ttsoptions->setText(userSettings->value("ttsoptions","").toString());
155 userSettings->endGroup();
157 if(exepath == "")
160 //try autodetect tts
161 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
162 QStringList path = QString(getenv("PATH")).split(":", QString::SkipEmptyParts);
163 #elif defined(Q_OS_WIN)
164 QStringList path = QString(getenv("PATH")).split(";", QString::SkipEmptyParts);
165 #endif
166 qDebug() << path;
167 for(int i = 0; i < path.size(); i++)
169 QString executable = QDir::fromNativeSeparators(path.at(i)) + "/" + m_name;
170 #if defined(Q_OS_WIN)
171 executable += ".exe";
172 QStringList ex = executable.split("\"", QString::SkipEmptyParts);
173 executable = ex.join("");
174 #endif
175 qDebug() << executable;
176 if(QFileInfo(executable).isExecutable())
178 exepath= QDir::toNativeSeparators(executable);
179 break;
185 ui.ttspath->setText(exepath);
187 //show dialog
188 this->exec();
192 void TTSExes::accept(void)
194 if(userSettings != NULL)
196 //save settings in user config
197 userSettings->beginGroup(m_name);
198 userSettings->setValue("ttspath",ui.ttspath->text());
199 userSettings->setValue("ttsoptions",ui.ttsoptions->text());
200 userSettings->endGroup();
201 // sync settings
202 userSettings->sync();
204 this->close();
207 void TTSExes::reject(void)
209 this->close();
212 bool TTSExes::configOk()
214 userSettings->beginGroup(m_name);
215 QString path = userSettings->value("ttspath","").toString();
216 userSettings->endGroup();
218 if (QFileInfo(path).exists())
219 return true;
221 return false;
224 void TTSExes::browse()
226 BrowseDirtree browser(this);
227 browser.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
229 if(QFileInfo(ui.ttspath->text()).isDir())
231 browser.setDir(ui.ttspath->text());
233 if(browser.exec() == QDialog::Accepted)
235 qDebug() << browser.getSelected();
236 QString exe = browser.getSelected();
237 if(!QFileInfo(exe).isExecutable())
238 return;
239 ui.ttspath->setText(exe);
243 /*********************************************************************
244 * TTS Sapi
245 **********************************************************************/
246 TTSSapi::TTSSapi(QWidget *parent) : TTSBase(parent)
248 m_TTSTemplate = "cscript //nologo \"%exe\" /language:%lang /voice:\"%voice\" /speed:%speed \"%options\"";
249 defaultLanguage ="english";
250 ui.setupUi(this);
251 this->hide();
252 connect(ui.reset,SIGNAL(clicked()),this,SLOT(reset()));
253 connect(ui.languagecombo,SIGNAL(currentIndexChanged(QString)),this,SLOT(updateVoices(QString)));
257 bool TTSSapi::start(QString *errStr)
260 userSettings->beginGroup("sapi");
261 m_TTSOpts = userSettings->value("ttsoptions","").toString();
262 m_TTSLanguage =userSettings->value("ttslanguage","").toString();
263 m_TTSVoice=userSettings->value("ttsvoice","").toString();
264 m_TTSSpeed=userSettings->value("ttsspeed","").toString();
265 userSettings->endGroup();
267 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
268 QFile::copy(":/builtin/sapi_voice.vbs",QDir::tempPath() + "/sapi_voice.vbs");
269 m_TTSexec = QDir::tempPath() +"/sapi_voice.vbs";
271 QFileInfo tts(m_TTSexec);
272 if(!tts.exists())
274 *errStr = tr("Could not copy the Sapi-script");
275 return false;
277 // create the voice process
278 QString execstring = m_TTSTemplate;
279 execstring.replace("%exe",m_TTSexec);
280 execstring.replace("%options",m_TTSOpts);
281 execstring.replace("%lang",m_TTSLanguage);
282 execstring.replace("%voice",m_TTSVoice);
283 execstring.replace("%speed",m_TTSSpeed);
285 qDebug() << "init" << execstring;
286 voicescript = new QProcess(NULL);
287 //connect(voicescript,SIGNAL(readyReadStandardError()),this,SLOT(error()));
289 voicescript->start(execstring);
290 if(!voicescript->waitForStarted())
292 *errStr = tr("Could not start the Sapi-script");
293 return false;
296 if(!voicescript->waitForReadyRead(100))
298 *errStr = voicescript->readAllStandardError();
299 if(*errStr != "")
300 return false;
302 return true;
306 QStringList TTSSapi::getVoiceList(QString language)
308 QStringList result;
310 QFile::copy(":/builtin/sapi_voice.vbs",QDir::tempPath() + "/sapi_voice.vbs");
311 m_TTSexec = QDir::tempPath() +"/sapi_voice.vbs";
313 QFileInfo tts(m_TTSexec);
314 if(!tts.exists())
315 return result;
317 // create the voice process
318 QString execstring = "cscript //nologo \"%exe\" /language:%lang /listvoices";;
319 execstring.replace("%exe",m_TTSexec);
320 execstring.replace("%lang",language);
321 qDebug() << "init" << execstring;
322 voicescript = new QProcess(NULL);
323 voicescript->start(execstring);
324 if(!voicescript->waitForStarted())
325 return result;
327 voicescript->waitForReadyRead();
329 QString dataRaw = voicescript->readAllStandardError().data();
330 result = dataRaw.split(",",QString::SkipEmptyParts);
331 result.sort();
332 result.removeFirst();
334 delete voicescript;
335 QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",QFile::ReadOwner |QFile::WriteOwner|QFile::ExeOwner
336 |QFile::ReadUser| QFile::WriteUser| QFile::ExeUser
337 |QFile::ReadGroup |QFile::WriteGroup |QFile::ExeGroup
338 |QFile::ReadOther |QFile::WriteOther |QFile::ExeOther );
339 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
341 return result;
344 void TTSSapi::updateVoices(QString language)
346 QStringList Voices = getVoiceList(language);
347 ui.voicecombo->clear();
348 ui.voicecombo->addItems(Voices);
353 bool TTSSapi::voice(QString text,QString wavfile)
355 QString query = "SPEAK\t"+wavfile+"\t"+text+"\r\n";
356 qDebug() << "voicing" << query;
357 voicescript->write(query.toUtf8());
358 voicescript->write("SYNC\tbla\r\n");
359 voicescript->waitForReadyRead();
360 return true;
363 bool TTSSapi::stop()
365 QString query = "QUIT\r\n";
366 voicescript->write(query.toUtf8());
367 voicescript->waitForFinished();
368 delete voicescript;
369 QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",QFile::ReadOwner |QFile::WriteOwner|QFile::ExeOwner
370 |QFile::ReadUser| QFile::WriteUser| QFile::ExeUser
371 |QFile::ReadGroup |QFile::WriteGroup |QFile::ExeGroup
372 |QFile::ReadOther |QFile::WriteOther |QFile::ExeOther );
373 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
374 return true;
378 void TTSSapi::reset()
380 ui.ttsoptions->setText("");
381 ui.languagecombo->setCurrentIndex(ui.languagecombo->findText(defaultLanguage));
384 void TTSSapi::showCfg()
386 // try to get config from settings
387 userSettings->beginGroup("sapi");
388 ui.ttsoptions->setText(userSettings->value("ttsoptions","").toString());
389 QString selLang = userSettings->value("ttslanguage",defaultLanguage).toString();
390 QString selVoice = userSettings->value("ttsvoice","").toString();
391 ui.speed->setValue(userSettings->value("ttsspeed",0).toInt());
392 userSettings->endGroup();
394 // fill in language combobox
396 deviceSettings->beginGroup("languages");
397 QStringList keys = deviceSettings->allKeys();
398 QStringList languages;
399 for(int i =0 ; i < keys.size();i++)
401 languages << deviceSettings->value(keys.at(i)).toString();
403 deviceSettings->endGroup();
405 languages.sort();
406 ui.languagecombo->clear();
407 ui.languagecombo->addItems(languages);
409 // set saved lang
410 ui.languagecombo->setCurrentIndex(ui.languagecombo->findText(selLang));
412 // fill in voice combobox
413 updateVoices(selLang);
415 // set saved lang
416 ui.voicecombo->setCurrentIndex(ui.voicecombo->findText(selVoice));
418 //show dialog
419 this->exec();
423 void TTSSapi::accept(void)
425 if(userSettings != NULL)
427 //save settings in user config
428 userSettings->beginGroup("sapi");
429 userSettings->setValue("ttsoptions",ui.ttsoptions->text());
430 userSettings->setValue("ttslanguage",ui.languagecombo->currentText());
431 userSettings->setValue("ttsvoice",ui.voicecombo->currentText());
432 userSettings->setValue("ttsspeed",QString("%1").arg(ui.speed->value()));
433 userSettings->endGroup();
434 // sync settings
435 userSettings->sync();
437 this->close();
440 void TTSSapi::reject(void)
442 this->close();
445 bool TTSSapi::configOk()
447 return true;