Replaced TAB characters by spaces in sansapatcher
[kugel-rb.git] / rbutil / rbutilqt / tts.cpp
blobc603e148f140b5a9e22165f474c14d2a2dc3d862
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2007 by Dominik Wenger
10 * $Id$
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"
23 // static variables
24 QMap<QString,QString> TTSBase::ttsList;
25 QMap<QString,TTSBase*> TTSBase::ttsCache;
27 // static functions
28 void TTSBase::initTTSList()
30 ttsList["espeak"] = "Espeak TTS Engine";
31 ttsList["flite"] = "Flite TTS Engine";
32 ttsList["swift"] = "Swift TTS Engine";
33 #if defined(Q_OS_WIN)
34 ttsList["sapi"] = "Sapi TTS Engine";
35 #endif
39 // function to get a specific encoder
40 TTSBase* TTSBase::getTTS(QString ttsName)
42 // check cache
43 if(ttsCache.contains(ttsName))
44 return ttsCache.value(ttsName);
46 TTSBase* tts;
47 if(ttsName == "sapi")
49 tts = new TTSSapi();
50 ttsCache[ttsName] = tts;
51 return tts;
53 else
55 tts = new TTSExes(ttsName);
56 ttsCache[ttsName] = tts;
57 return tts;
61 // get the list of encoders, nice names
62 QStringList TTSBase::getTTSList()
64 // init list if its empty
65 if(ttsList.count() == 0)
66 initTTSList();
68 return ttsList.keys();
71 // get nice name of a specific tts
72 QString TTSBase::getTTSName(QString tts)
74 if(ttsList.isEmpty())
75 initTTSList();
76 return ttsList.value(tts);
79 /*********************************************************************
80 * TTS Base
81 **********************************************************************/
82 TTSBase::TTSBase(): QObject()
87 /*********************************************************************
88 * General TTS Exes
89 **********************************************************************/
90 TTSExes::TTSExes(QString name) : TTSBase()
92 m_name = name;
94 m_TemplateMap["espeak"] = "\"%exe\" %options -w \"%wavfile\" \"%text\"";
95 m_TemplateMap["flite"] = "\"%exe\" %options -o \"%wavfile\" \"%text\"";
96 m_TemplateMap["swift"] = "\"%exe\" %options -o \"%wavfile\" \"%text\"";
100 void TTSExes::setCfg(RbSettings* sett)
102 // call function of base class
103 TTSBase::setCfg(sett);
105 // if the config isnt OK, try to autodetect
106 if(!configOk())
108 QString exepath;
109 //try autodetect tts
110 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
111 QStringList path = QString(getenv("PATH")).split(":", QString::SkipEmptyParts);
112 #elif defined(Q_OS_WIN)
113 QStringList path = QString(getenv("PATH")).split(";", QString::SkipEmptyParts);
114 #endif
115 qDebug() << path;
116 for(int i = 0; i < path.size(); i++)
118 QString executable = QDir::fromNativeSeparators(path.at(i)) + "/" + m_name;
119 #if defined(Q_OS_WIN)
120 executable += ".exe";
121 QStringList ex = executable.split("\"", QString::SkipEmptyParts);
122 executable = ex.join("");
123 #endif
124 qDebug() << executable;
125 if(QFileInfo(executable).isExecutable())
127 exepath= QDir::toNativeSeparators(executable);
128 break;
131 settings->setTTSPath(m_name,exepath);
132 settings->sync();
137 bool TTSExes::start(QString *errStr)
139 m_TTSexec = settings->ttsPath(m_name);
140 m_TTSOpts = settings->ttsOptions(m_name);
142 m_TTSTemplate = m_TemplateMap.value(m_name);
144 QFileInfo tts(m_TTSexec);
145 if(tts.exists())
147 return true;
149 else
151 *errStr = tr("TTS executable not found");
152 return false;
156 bool TTSExes::voice(QString text,QString wavfile)
158 QString execstring = m_TTSTemplate;
160 execstring.replace("%exe",m_TTSexec);
161 execstring.replace("%options",m_TTSOpts);
162 execstring.replace("%wavfile",wavfile);
163 execstring.replace("%text",text);
164 //qDebug() << "voicing" << execstring;
165 QProcess::execute(execstring);
166 return true;
170 void TTSExes::showCfg()
172 #ifndef CONSOLE
173 TTSExesGui gui;
174 #else
175 TTSExesGuiCli gui;
176 #endif
177 gui.setCfg(settings);
178 gui.showCfg(m_name);
181 bool TTSExes::configOk()
183 QString path = settings->ttsPath(m_name);
185 if (QFileInfo(path).exists())
186 return true;
188 return false;
191 /*********************************************************************
192 * TTS Sapi
193 **********************************************************************/
194 TTSSapi::TTSSapi() : TTSBase()
196 m_TTSTemplate = "cscript //nologo \"%exe\" /language:%lang /voice:\"%voice\" /speed:%speed \"%options\"";
197 defaultLanguage ="english";
198 m_sapi4 =false;
202 bool TTSSapi::start(QString *errStr)
205 m_TTSOpts = settings->ttsOptions("sapi");
206 m_TTSLanguage =settings->ttsLang("sapi");
207 m_TTSVoice=settings->ttsVoice("sapi");
208 m_TTSSpeed=QString("%1").arg(settings->ttsSpeed("sapi"));
209 m_sapi4 = settings->ttsUseSapi4();
211 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
212 QFile::copy(":/builtin/sapi_voice.vbs",QDir::tempPath() + "/sapi_voice.vbs");
213 m_TTSexec = QDir::tempPath() +"/sapi_voice.vbs";
215 QFileInfo tts(m_TTSexec);
216 if(!tts.exists())
218 *errStr = tr("Could not copy the Sapi-script");
219 return false;
221 // create the voice process
222 QString execstring = m_TTSTemplate;
223 execstring.replace("%exe",m_TTSexec);
224 execstring.replace("%options",m_TTSOpts);
225 execstring.replace("%lang",m_TTSLanguage);
226 execstring.replace("%voice",m_TTSVoice);
227 execstring.replace("%speed",m_TTSSpeed);
229 if(m_sapi4)
230 execstring.append(" /sapi4 ");
232 qDebug() << "init" << execstring;
233 voicescript = new QProcess(NULL);
234 //connect(voicescript,SIGNAL(readyReadStandardError()),this,SLOT(error()));
236 voicescript->start(execstring);
237 if(!voicescript->waitForStarted())
239 *errStr = tr("Could not start the Sapi-script");
240 return false;
243 if(!voicescript->waitForReadyRead(300))
245 *errStr = voicescript->readAllStandardError();
246 if(*errStr != "")
247 return false;
249 return true;
253 QStringList TTSSapi::getVoiceList(QString language)
255 QStringList result;
257 QFile::copy(":/builtin/sapi_voice.vbs",QDir::tempPath() + "/sapi_voice.vbs");
258 m_TTSexec = QDir::tempPath() +"/sapi_voice.vbs";
260 QFileInfo tts(m_TTSexec);
261 if(!tts.exists())
262 return result;
264 // create the voice process
265 QString execstring = "cscript //nologo \"%exe\" /language:%lang /listvoices";
266 execstring.replace("%exe",m_TTSexec);
267 execstring.replace("%lang",language);
269 if(settings->ttsUseSapi4())
270 execstring.append(" /sapi4 ");
272 qDebug() << "init" << execstring;
273 voicescript = new QProcess(NULL);
274 voicescript->start(execstring);
275 if(!voicescript->waitForStarted())
276 return result;
278 voicescript->waitForReadyRead();
280 QString dataRaw = voicescript->readAllStandardError().data();
281 result = dataRaw.split(",",QString::SkipEmptyParts);
282 result.sort();
283 result.removeFirst();
284 for(int i = 0; i< result.size();i++)
286 result[i] = result.at(i).simplified();
290 delete voicescript;
291 QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",QFile::ReadOwner |QFile::WriteOwner|QFile::ExeOwner
292 |QFile::ReadUser| QFile::WriteUser| QFile::ExeUser
293 |QFile::ReadGroup |QFile::WriteGroup |QFile::ExeGroup
294 |QFile::ReadOther |QFile::WriteOther |QFile::ExeOther );
295 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
297 return result;
302 bool TTSSapi::voice(QString text,QString wavfile)
304 QString query = "SPEAK\t"+wavfile+"\t"+text+"\r\n";
305 qDebug() << "voicing" << query;
306 voicescript->write(query.toLocal8Bit());
307 voicescript->write("SYNC\tbla\r\n");
308 voicescript->waitForReadyRead();
309 return true;
312 bool TTSSapi::stop()
314 QString query = "QUIT\r\n";
315 voicescript->write(query.toLocal8Bit());
316 voicescript->waitForFinished();
317 delete voicescript;
318 QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",QFile::ReadOwner |QFile::WriteOwner|QFile::ExeOwner
319 |QFile::ReadUser| QFile::WriteUser| QFile::ExeUser
320 |QFile::ReadGroup |QFile::WriteGroup |QFile::ExeGroup
321 |QFile::ReadOther |QFile::WriteOther |QFile::ExeOther );
322 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
323 return true;
327 void TTSSapi::showCfg()
329 #ifndef CONSOLE
330 TTSSapiGui gui(this);
331 #else
332 TTSSapiGuiCli gui(this);
333 #endif
334 gui.setCfg(settings);
335 gui.showCfg();
338 bool TTSSapi::configOk()
340 if(settings->ttsVoice("sapi").isEmpty())
341 return false;
342 return true;