diff options
Diffstat (limited to 'rbutil/rbutilqt/tts.cpp')
-rw-r--r-- | rbutil/rbutilqt/tts.cpp | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/rbutil/rbutilqt/tts.cpp b/rbutil/rbutilqt/tts.cpp new file mode 100644 index 0000000000..63e1188851 --- /dev/null +++ b/rbutil/rbutilqt/tts.cpp | |||
@@ -0,0 +1,376 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2007 by Dominik Wenger | ||
10 | * $Id: tts.cpp 15212 2007-10-19 21:49:07Z domonoky $ | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include "tts.h" | ||
21 | |||
22 | #include "browsedirtree.h" | ||
23 | |||
24 | static QMap<QString,QString> ttsList; | ||
25 | static QMap<QString,TTSBase*> ttsCache; | ||
26 | |||
27 | void initTTSList() | ||
28 | { | ||
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 | ||
35 | |||
36 | } | ||
37 | |||
38 | // function to get a specific encoder | ||
39 | TTSBase* getTTS(QString ttsname) | ||
40 | { | ||
41 | // init list if its empty | ||
42 | if(ttsList.count() == 0) initTTSList(); | ||
43 | |||
44 | QString ttsName = ttsList.key(ttsname); | ||
45 | |||
46 | // check cache | ||
47 | if(ttsCache.contains(ttsName)) | ||
48 | return ttsCache.value(ttsName); | ||
49 | |||
50 | TTSBase* tts; | ||
51 | if(ttsName == "sapi") | ||
52 | { | ||
53 | tts = new TTSSapi(); | ||
54 | ttsCache[ttsName] = tts; | ||
55 | return tts; | ||
56 | } | ||
57 | else | ||
58 | { | ||
59 | tts = new TTSExes(ttsName); | ||
60 | ttsCache[ttsName] = tts; | ||
61 | return tts; | ||
62 | } | ||
63 | } | ||
64 | |||
65 | // get the list of encoders, nice names | ||
66 | QStringList getTTSList() | ||
67 | { | ||
68 | // init list if its empty | ||
69 | if(ttsList.count() == 0) initTTSList(); | ||
70 | |||
71 | QStringList ttsNameList; | ||
72 | QMapIterator<QString, QString> i(ttsList); | ||
73 | while (i.hasNext()) { | ||
74 | i.next(); | ||
75 | ttsNameList << i.value(); | ||
76 | } | ||
77 | |||
78 | return ttsNameList; | ||
79 | } | ||
80 | |||
81 | |||
82 | /********************************************************************* | ||
83 | * TTS Base | ||
84 | **********************************************************************/ | ||
85 | TTSBase::TTSBase(QWidget *parent): QDialog(parent) | ||
86 | { | ||
87 | |||
88 | } | ||
89 | |||
90 | /********************************************************************* | ||
91 | * General TTS Exes | ||
92 | **********************************************************************/ | ||
93 | TTSExes::TTSExes(QString name,QWidget *parent) : TTSBase(parent) | ||
94 | { | ||
95 | m_name = name; | ||
96 | |||
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\""; | ||
100 | |||
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())); | ||
105 | } | ||
106 | |||
107 | bool TTSExes::start() | ||
108 | { | ||
109 | userSettings->beginGroup(m_name); | ||
110 | m_TTSexec = userSettings->value("ttspath","").toString(); | ||
111 | m_TTSOpts = userSettings->value("ttsoptions","").toString(); | ||
112 | userSettings->endGroup(); | ||
113 | |||
114 | m_TTSTemplate = m_TemplateMap.value(m_name); | ||
115 | |||
116 | QFileInfo tts(m_TTSexec); | ||
117 | if(tts.exists()) | ||
118 | { | ||
119 | return true; | ||
120 | } | ||
121 | else | ||
122 | { | ||
123 | return false; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | bool TTSExes::voice(QString text,QString wavfile) | ||
128 | { | ||
129 | QString execstring = m_TTSTemplate; | ||
130 | |||
131 | execstring.replace("%exe",m_TTSexec); | ||
132 | execstring.replace("%options",m_TTSOpts); | ||
133 | execstring.replace("%wavfile",wavfile); | ||
134 | execstring.replace("%text",text); | ||
135 | //qDebug() << "voicing" << execstring; | ||
136 | QProcess::execute(execstring); | ||
137 | return true; | ||
138 | |||
139 | } | ||
140 | |||
141 | |||
142 | void TTSExes::reset() | ||
143 | { | ||
144 | ui.ttspath->setText(""); | ||
145 | ui.ttsoptions->setText(""); | ||
146 | } | ||
147 | |||
148 | void TTSExes::showCfg() | ||
149 | { | ||
150 | // try to get config from settings | ||
151 | userSettings->beginGroup(m_name); | ||
152 | QString exepath =userSettings->value("ttspath","").toString(); | ||
153 | ui.ttsoptions->setText(userSettings->value("ttsoptions","").toString()); | ||
154 | userSettings->endGroup(); | ||
155 | |||
156 | if(exepath == "") | ||
157 | { | ||
158 | |||
159 | //try autodetect tts | ||
160 | #if defined(Q_OS_LINUX) || defined(Q_OS_MACX) | ||
161 | QStringList path = QString(getenv("PATH")).split(":", QString::SkipEmptyParts); | ||
162 | #elif defined(Q_OS_WIN) | ||
163 | QStringList path = QString(getenv("PATH")).split(";", QString::SkipEmptyParts); | ||
164 | #endif | ||
165 | qDebug() << path; | ||
166 | for(int i = 0; i < path.size(); i++) | ||
167 | { | ||
168 | QString executable = QDir::fromNativeSeparators(path.at(i)) + "/" + m_name; | ||
169 | #if defined(Q_OS_WIN) | ||
170 | executable += ".exe"; | ||
171 | QStringList ex = executable.split("\"", QString::SkipEmptyParts); | ||
172 | executable = ex.join(""); | ||
173 | #endif | ||
174 | qDebug() << executable; | ||
175 | if(QFileInfo(executable).isExecutable()) | ||
176 | { | ||
177 | exepath= QDir::toNativeSeparators(executable); | ||
178 | break; | ||
179 | } | ||
180 | } | ||
181 | |||
182 | } | ||
183 | |||
184 | ui.ttspath->setText(exepath); | ||
185 | |||
186 | //show dialog | ||
187 | this->exec(); | ||
188 | |||
189 | } | ||
190 | |||
191 | void TTSExes::accept(void) | ||
192 | { | ||
193 | if(userSettings != NULL) | ||
194 | { | ||
195 | //save settings in user config | ||
196 | userSettings->beginGroup(m_name); | ||
197 | userSettings->setValue("ttspath",ui.ttspath->text()); | ||
198 | userSettings->setValue("ttsoptions",ui.ttsoptions->text()); | ||
199 | userSettings->endGroup(); | ||
200 | // sync settings | ||
201 | userSettings->sync(); | ||
202 | } | ||
203 | this->close(); | ||
204 | } | ||
205 | |||
206 | void TTSExes::reject(void) | ||
207 | { | ||
208 | this->close(); | ||
209 | } | ||
210 | |||
211 | bool TTSExes::configOk() | ||
212 | { | ||
213 | userSettings->beginGroup(m_name); | ||
214 | QString path = userSettings->value("ttspath","").toString(); | ||
215 | userSettings->endGroup(); | ||
216 | |||
217 | if (QFileInfo(path).exists()) | ||
218 | return true; | ||
219 | |||
220 | return false; | ||
221 | } | ||
222 | |||
223 | void TTSExes::browse() | ||
224 | { | ||
225 | BrowseDirtree browser(this); | ||
226 | browser.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); | ||
227 | |||
228 | if(QFileInfo(ui.ttspath->text()).isDir()) | ||
229 | { | ||
230 | browser.setDir(ui.ttspath->text()); | ||
231 | } | ||
232 | if(browser.exec() == QDialog::Accepted) | ||
233 | { | ||
234 | qDebug() << browser.getSelected(); | ||
235 | QString exe = browser.getSelected(); | ||
236 | if(!QFileInfo(exe).isExecutable()) | ||
237 | return; | ||
238 | ui.ttspath->setText(exe); | ||
239 | } | ||
240 | } | ||
241 | |||
242 | /********************************************************************* | ||
243 | * TTS Sapi | ||
244 | **********************************************************************/ | ||
245 | TTSSapi::TTSSapi(QWidget *parent) : TTSBase(parent) | ||
246 | { | ||
247 | m_TTSTemplate = "cscript //nologo \"%exe\" /language:%lang \"%options\""; | ||
248 | defaultLanguage ="english"; | ||
249 | ui.setupUi(this); | ||
250 | this->hide(); | ||
251 | connect(ui.reset,SIGNAL(clicked()),this,SLOT(reset())); | ||
252 | connect(ui.browse,SIGNAL(clicked()),this,SLOT(browse())); | ||
253 | } | ||
254 | |||
255 | |||
256 | bool TTSSapi::start() | ||
257 | { | ||
258 | |||
259 | userSettings->beginGroup("sapi"); | ||
260 | m_TTSexec = userSettings->value("ttspath","").toString(); | ||
261 | m_TTSOpts = userSettings->value("ttsoptions","").toString(); | ||
262 | m_TTSLanguage =userSettings->value("ttslanguage","").toString(); | ||
263 | userSettings->endGroup(); | ||
264 | |||
265 | QFileInfo tts(m_TTSexec); | ||
266 | if(!tts.exists()) | ||
267 | return false; | ||
268 | |||
269 | // create the voice process | ||
270 | QString execstring = m_TTSTemplate; | ||
271 | execstring.replace("%exe",m_TTSexec); | ||
272 | execstring.replace("%options",m_TTSOpts); | ||
273 | execstring.replace("%lang",m_TTSLanguage); | ||
274 | qDebug() << "init" << execstring; | ||
275 | voicescript = new QProcess(NULL); | ||
276 | voicescript->start(execstring); | ||
277 | if(!voicescript->waitForStarted()) | ||
278 | return false; | ||
279 | return true; | ||
280 | } | ||
281 | |||
282 | bool TTSSapi::voice(QString text,QString wavfile) | ||
283 | { | ||
284 | QString query = "SPEAK\t"+wavfile+"\t"+text+"\r\n"; | ||
285 | qDebug() << "voicing" << query; | ||
286 | voicescript->write(query.toLocal8Bit()); | ||
287 | voicescript->write("SYNC\tbla\r\n"); | ||
288 | voicescript->waitForReadyRead(); | ||
289 | return true; | ||
290 | } | ||
291 | |||
292 | bool TTSSapi::stop() | ||
293 | { | ||
294 | QString query = "QUIT\r\n"; | ||
295 | voicescript->write(query.toLocal8Bit()); | ||
296 | voicescript->waitForFinished(); | ||
297 | delete voicescript; | ||
298 | return true; | ||
299 | } | ||
300 | |||
301 | |||
302 | void TTSSapi::reset() | ||
303 | { | ||
304 | ui.ttspath->setText(""); | ||
305 | ui.ttsoptions->setText(""); | ||
306 | ui.ttslanguage->setText(defaultLanguage); | ||
307 | } | ||
308 | |||
309 | void TTSSapi::showCfg() | ||
310 | { | ||
311 | // try to get config from settings | ||
312 | userSettings->beginGroup("sapi"); | ||
313 | QString exepath =userSettings->value("ttspath","").toString(); | ||
314 | ui.ttsoptions->setText(userSettings->value("ttsoptions","").toString()); | ||
315 | ui.ttslanguage->setText(userSettings->value("ttsoptions",defaultLanguage).toString()); | ||
316 | userSettings->endGroup(); | ||
317 | |||
318 | ui.ttspath->setText(exepath); | ||
319 | |||
320 | //show dialog | ||
321 | this->exec(); | ||
322 | |||
323 | } | ||
324 | |||
325 | void TTSSapi::accept(void) | ||
326 | { | ||
327 | if(userSettings != NULL) | ||
328 | { | ||
329 | //save settings in user config | ||
330 | userSettings->beginGroup("sapi"); | ||
331 | userSettings->setValue("ttspath",ui.ttspath->text()); | ||
332 | userSettings->setValue("ttsoptions",ui.ttsoptions->text()); | ||
333 | userSettings->setValue("ttslanguage",ui.ttslanguage->text()); | ||
334 | userSettings->endGroup(); | ||
335 | // sync settings | ||
336 | userSettings->sync(); | ||
337 | } | ||
338 | this->close(); | ||
339 | } | ||
340 | |||
341 | void TTSSapi::reject(void) | ||
342 | { | ||
343 | this->close(); | ||
344 | } | ||
345 | |||
346 | bool TTSSapi::configOk() | ||
347 | { | ||
348 | userSettings->beginGroup("sapi"); | ||
349 | QString path = userSettings->value("ttspath","").toString(); | ||
350 | userSettings->endGroup(); | ||
351 | |||
352 | if (QFileInfo(path).exists()) | ||
353 | return true; | ||
354 | |||
355 | return false; | ||
356 | } | ||
357 | |||
358 | void TTSSapi::browse() | ||
359 | { | ||
360 | BrowseDirtree browser(this); | ||
361 | browser.setFilter(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); | ||
362 | |||
363 | if(QFileInfo(ui.ttspath->text()).isDir()) | ||
364 | { | ||
365 | browser.setDir(ui.ttspath->text()); | ||
366 | } | ||
367 | if(browser.exec() == QDialog::Accepted) | ||
368 | { | ||
369 | qDebug() << browser.getSelected(); | ||
370 | QString exe = browser.getSelected(); | ||
371 | if(!QFileInfo(exe).isExecutable()) | ||
372 | return; | ||
373 | ui.ttspath->setText(exe); | ||
374 | } | ||
375 | } | ||
376 | |||