1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2007 by Dominik Wenger
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 ****************************************************************************/
24 QMap
<QString
,QString
> TTSBase::ttsList
;
25 QMap
<QString
,TTSBase
*> TTSBase::ttsCache
;
28 void TTSBase::initTTSList()
30 ttsList
["espeak"] = "Espeak TTS Engine";
31 ttsList
["flite"] = "Flite TTS Engine";
32 ttsList
["swift"] = "Swift TTS Engine";
34 ttsList
["sapi"] = "Sapi TTS Engine";
39 // function to get a specific encoder
40 TTSBase
* TTSBase::getTTS(QString ttsName
)
43 if(ttsCache
.contains(ttsName
))
44 return ttsCache
.value(ttsName
);
50 ttsCache
[ttsName
] = tts
;
55 tts
= new TTSExes(ttsName
);
56 ttsCache
[ttsName
] = tts
;
61 // get the list of encoders, nice names
62 QStringList
TTSBase::getTTSList()
64 // init list if its empty
65 if(ttsList
.count() == 0)
68 return ttsList
.keys();
71 // get nice name of a specific tts
72 QString
TTSBase::getTTSName(QString tts
)
76 return ttsList
.value(tts
);
79 /*********************************************************************
81 **********************************************************************/
82 TTSBase::TTSBase(): QObject()
87 /*********************************************************************
89 **********************************************************************/
90 TTSExes::TTSExes(QString name
) : TTSBase()
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
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
);
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("");
124 qDebug() << executable
;
125 if(QFileInfo(executable
).isExecutable())
127 exepath
= QDir::toNativeSeparators(executable
);
131 settings
->setTTSPath(m_name
,exepath
);
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
);
151 *errStr
= tr("TTS executable not found");
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
);
170 void TTSExes::showCfg()
177 gui
.setCfg(settings
);
181 bool TTSExes::configOk()
183 QString path
= settings
->ttsPath(m_name
);
185 if (QFileInfo(path
).exists())
191 /*********************************************************************
193 **********************************************************************/
194 TTSSapi::TTSSapi() : TTSBase()
196 m_TTSTemplate
= "cscript //nologo \"%exe\" /language:%lang /voice:\"%voice\" /speed:%speed \"%options\"";
197 defaultLanguage
="english";
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
);
218 *errStr
= tr("Could not copy the Sapi-script");
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
);
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");
243 if(!voicescript
->waitForReadyRead(300))
245 *errStr
= voicescript
->readAllStandardError();
250 voicestream
= new QTextStream(voicescript
);
251 voicestream
->setCodec("UTF16-LE");
257 QStringList
TTSSapi::getVoiceList(QString language
)
261 QFile::copy(":/builtin/sapi_voice.vbs",QDir::tempPath() + "/sapi_voice.vbs");
262 m_TTSexec
= QDir::tempPath() +"/sapi_voice.vbs";
264 QFileInfo
tts(m_TTSexec
);
268 // create the voice process
269 QString execstring
= "cscript //nologo \"%exe\" /language:%lang /listvoices";
270 execstring
.replace("%exe",m_TTSexec
);
271 execstring
.replace("%lang",language
);
273 if(settings
->ttsUseSapi4())
274 execstring
.append(" /sapi4 ");
276 qDebug() << "init" << execstring
;
277 voicescript
= new QProcess(NULL
);
278 voicescript
->start(execstring
);
279 qDebug() << "wait for started";
280 if(!voicescript
->waitForStarted())
282 voicescript
->closeWriteChannel();
283 voicescript
->waitForReadyRead();
285 QString dataRaw
= voicescript
->readAllStandardError().data();
286 result
= dataRaw
.split(",",QString::SkipEmptyParts
);
288 result
.removeFirst();
289 for(int i
= 0; i
< result
.size();i
++)
291 result
[i
] = result
.at(i
).simplified();
296 QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",QFile::ReadOwner
|QFile::WriteOwner
|QFile::ExeOwner
297 |QFile::ReadUser
| QFile::WriteUser
| QFile::ExeUser
298 |QFile::ReadGroup
|QFile::WriteGroup
|QFile::ExeGroup
299 |QFile::ReadOther
|QFile::WriteOther
|QFile::ExeOther
);
300 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
307 bool TTSSapi::voice(QString text
,QString wavfile
)
309 QString query
= "SPEAK\t"+wavfile
+"\t"+text
+"\r\n";
310 qDebug() << "voicing" << query
;
311 *voicestream
<< query
;
312 *voicestream
<< "SYNC\tbla\r\n";
313 voicestream
->flush();
314 voicescript
->waitForReadyRead();
321 *voicestream
<< "QUIT\r\n";
322 voicestream
->flush();
323 voicescript
->waitForFinished();
326 QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",QFile::ReadOwner
|QFile::WriteOwner
|QFile::ExeOwner
327 |QFile::ReadUser
| QFile::WriteUser
| QFile::ExeUser
328 |QFile::ReadGroup
|QFile::WriteGroup
|QFile::ExeGroup
329 |QFile::ReadOther
|QFile::WriteOther
|QFile::ExeOther
);
330 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
335 void TTSSapi::showCfg()
338 TTSSapiGui
gui(this);
340 TTSSapiGuiCli
gui(this);
342 gui
.setCfg(settings
);
346 bool TTSSapi::configOk()
348 if(settings
->ttsVoice("sapi").isEmpty())