Fix advanced EQ menu
[maemo-rb.git] / rbutil / rbutilqt / base / talkgenerator.cpp
bloba2ab578adeddd38b0dfd09f2b652d6d2f3808aec
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2007 by Dominik Wenger
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
17 ****************************************************************************/
19 #include "talkgenerator.h"
20 #include "rbsettings.h"
21 #include "systeminfo.h"
22 #include "wavtrim.h"
24 TalkGenerator::TalkGenerator(QObject* parent): QObject(parent)
29 //! \brief Creates Talkfiles.
30 //!
31 TalkGenerator::Status TalkGenerator::process(QList<TalkEntry>* list,int wavtrimth)
33 m_abort = false;
34 QString errStr;
35 bool warnings = false;
37 //tts
38 emit logItem(tr("Starting TTS Engine"), LOGINFO);
39 m_tts = TTSBase::getTTS(this, RbSettings::value(RbSettings::Tts).toString());
40 if(!m_tts)
42 qDebug() << "[TalkGenerator] getting the TTS object failed!";
43 emit logItem(tr("Init of TTS engine failed"), LOGERROR);
44 emit done(true);
45 return eERROR;
47 if(!m_tts->start(&errStr))
49 emit logItem(errStr.trimmed(),LOGERROR);
50 emit logItem(tr("Init of TTS engine failed"), LOGERROR);
51 emit done(true);
52 return eERROR;
54 QCoreApplication::processEvents();
56 // Encoder
57 emit logItem(tr("Starting Encoder Engine"),LOGINFO);
58 m_enc = EncoderBase::getEncoder(this,SystemInfo::value(SystemInfo::CurEncoder).toString());
59 if(!m_enc->start())
61 emit logItem(tr("Init of Encoder engine failed"),LOGERROR);
62 emit done(true);
63 m_tts->stop();
64 return eERROR;
66 QCoreApplication::processEvents();
68 emit logProgress(0,0);
70 // Voice entries
71 emit logItem(tr("Voicing entries..."),LOGINFO);
72 Status voiceStatus= voiceList(list,wavtrimth);
73 if(voiceStatus == eERROR)
75 m_tts->stop();
76 m_enc->stop();
77 emit done(true);
78 return eERROR;
80 else if( voiceStatus == eWARNING)
81 warnings = true;
83 QCoreApplication::processEvents();
85 // Encoding Entries
86 emit logItem(tr("Encoding files..."),LOGINFO);
87 Status encoderStatus = encodeList(list);
88 if( encoderStatus == eERROR)
90 m_tts->stop();
91 m_enc->stop();
92 emit done(true);
93 return eERROR;
95 else if( voiceStatus == eWARNING)
96 warnings = true;
98 QCoreApplication::processEvents();
100 m_tts->stop();
101 m_enc->stop();
102 emit logProgress(1,1);
104 if(warnings)
105 return eWARNING;
106 return eOK;
109 //! \brief Voices a List of string
111 TalkGenerator::Status TalkGenerator::voiceList(QList<TalkEntry>* list,int wavtrimth)
113 int progressMax = list->size();
114 int m_progress = 0;
115 emit logProgress(m_progress,progressMax);
117 QStringList errors;
118 QStringList duplicates;
120 bool warnings = false;
121 for(int i=0; i < list->size(); i++)
123 if(m_abort)
125 emit logItem(tr("Voicing aborted"), LOGERROR);
126 return eERROR;
129 // skip duplicated wav entrys
130 if(!duplicates.contains(list->at(i).wavfilename))
131 duplicates.append(list->at(i).wavfilename);
132 else
134 qDebug() << "[TalkGenerator] duplicate skipped";
135 (*list)[i].voiced = true;
136 emit logProgress(++m_progress,progressMax);
137 continue;
140 // skip already voiced entrys
141 if(list->at(i).voiced == true)
143 emit logProgress(++m_progress,progressMax);
144 continue;
146 // skip entry whith empty text
147 if(list->at(i).toSpeak == "")
149 emit logProgress(++m_progress,progressMax);
150 continue;
153 // voice entry
154 QString error;
155 qDebug() << "[TalkGenerator] voicing: " << list->at(i).toSpeak
156 << "to" << list->at(i).wavfilename;
157 TTSStatus status = m_tts->voice(list->at(i).toSpeak,list->at(i).wavfilename, &error);
158 if(status == Warning)
160 warnings = true;
161 emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error),
162 LOGWARNING);
164 else if (status == FatalError)
166 emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error),
167 LOGERROR);
168 return eERROR;
170 else
171 (*list)[i].voiced = true;
173 // wavtrim if needed
174 if(wavtrimth != -1)
176 char buffer[255];
177 if(wavtrim(list->at(i).wavfilename.toLocal8Bit().data(),
178 wavtrimth, buffer, 255))
180 qDebug() << "[TalkGenerator] wavtrim returned error on"
181 << list->at(i).wavfilename;
182 return eERROR;
186 emit logProgress(++m_progress,progressMax);
187 QCoreApplication::processEvents();
189 if(warnings)
190 return eWARNING;
191 else
192 return eOK;
196 //! \brief Encodes a List of strings
198 TalkGenerator::Status TalkGenerator::encodeList(QList<TalkEntry>* list)
200 QStringList duplicates;
202 int progressMax = list->size();
203 int m_progress = 0;
204 emit logProgress(m_progress,progressMax);
206 for(int i=0; i < list->size(); i++)
208 if(m_abort)
210 emit logItem(tr("Encoding aborted"), LOGERROR);
211 return eERROR;
214 //skip non-voiced entrys
215 if(list->at(i).voiced == false)
217 qDebug() << "[TalkGenerator] non voiced entry detected:"
218 << list->at(i).toSpeak;
219 emit logProgress(++m_progress,progressMax);
220 continue;
222 //skip duplicates
223 if(!duplicates.contains(list->at(i).talkfilename))
224 duplicates.append(list->at(i).talkfilename);
225 else
227 qDebug() << "[TalkGenerator] duplicate skipped";
228 (*list)[i].encoded = true;
229 emit logProgress(++m_progress,progressMax);
230 continue;
233 //encode entry
234 qDebug() << "[TalkGenerator] encoding " << list->at(i).wavfilename
235 << "to" << list->at(i).talkfilename;
236 if(!m_enc->encode(list->at(i).wavfilename,list->at(i).talkfilename))
238 emit logItem(tr("Encoding of %1 failed").arg(
239 QFileInfo(list->at(i).wavfilename).baseName()), LOGERROR);
240 return eERROR;
242 (*list)[i].encoded = true;
243 emit logProgress(++m_progress,progressMax);
244 QCoreApplication::processEvents();
246 return eOK;
249 //! \brief slot, which is connected to the abort of the Logger.
250 //Sets a flag, so Creating Talkfiles ends at the next possible position
252 void TalkGenerator::abort()
254 m_abort = true;
257 QString TalkGenerator::correctString(QString s)
259 QString corrected = s;
260 int i = 0;
261 int max = m_corrections.size();
262 while(i < max) {
263 corrected = corrected.replace(QRegExp(m_corrections.at(i).search,
264 m_corrections.at(i).modifier.contains("i")
265 ? Qt::CaseInsensitive : Qt::CaseSensitive),
266 m_corrections.at(i).replace);
267 i++;
270 if(corrected != s)
271 qDebug() << "[VoiceFileCreator] corrected string" << s << "to" << corrected;
273 return corrected;
274 m_abort = true;
277 void TalkGenerator::setLang(QString name)
279 m_lang = name;
281 // re-initialize corrections list
282 m_corrections.clear();
283 QFile correctionsFile(":/builtin/voice-corrections.txt");
284 correctionsFile.open(QIODevice::ReadOnly);
286 QString engine = RbSettings::value(RbSettings::Tts).toString();
287 TTSBase* tts = TTSBase::getTTS(this,RbSettings::value(RbSettings::Tts).toString());
288 if(!tts)
290 qDebug() << "[TalkGenerator] getting the TTS object failed!";
291 return;
293 QString vendor = tts->voiceVendor();
294 delete tts;
296 if(m_lang.isEmpty())
297 m_lang = "english";
298 qDebug() << "[TalkGenerator] building string corrections list for"
299 << m_lang << engine << vendor;
300 QTextStream stream(&correctionsFile);
301 while(!stream.atEnd()) {
302 QString line = stream.readLine();
303 if(line.startsWith(" ") || line.length() < 10)
304 continue;
305 // separator is first character
306 QString separator = line.at(0);
307 line.remove(0, 1);
308 QStringList items = line.split(separator);
309 // we need to have at least 6 separate entries.
310 if(items.size() < 6)
311 continue;
313 QRegExp re_lang(items.at(0));
314 QRegExp re_engine(items.at(1));
315 QRegExp re_vendor(items.at(2));
316 if(!re_lang.exactMatch(m_lang)) {
317 continue;
319 if(!re_vendor.exactMatch(vendor)) {
320 continue;
322 if(!re_engine.exactMatch(engine)) {
323 continue;
325 struct CorrectionItems co;
326 co.search = items.at(3);
327 co.replace = items.at(4);
328 // Qt uses backslash for back references, Perl uses dollar sign.
329 co.replace.replace(QRegExp("\\$(\\d+)"), "\\\\1");
330 co.modifier = items.at(5);
331 m_corrections.append(co);
333 correctionsFile.close();