summaryrefslogtreecommitdiff
path: root/rbutil/rbutilqt/base/talkgenerator.cpp
diff options
context:
space:
mode:
authorDominik Wenger <domonoky@googlemail.com>2010-06-04 21:22:25 +0000
committerDominik Wenger <domonoky@googlemail.com>2010-06-04 21:22:25 +0000
commita8c1934c9d8d3618b78a2a15788f6d3cf5040ca4 (patch)
tree4d0b742e0cae5230529f9bdb933321f3b9336347 /rbutil/rbutilqt/base/talkgenerator.cpp
parent081bda8ab258c763e654067740f365be68269340 (diff)
downloadrockbox-a8c1934c9d8d3618b78a2a15788f6d3cf5040ca4.tar.gz
rockbox-a8c1934c9d8d3618b78a2a15788f6d3cf5040ca4.zip
rbutil: Make TTS and encoders run on all cores \n FS#11160 by Delyan Kratunov
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26558 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'rbutil/rbutilqt/base/talkgenerator.cpp')
-rw-r--r--rbutil/rbutilqt/base/talkgenerator.cpp220
1 files changed, 131 insertions, 89 deletions
diff --git a/rbutil/rbutilqt/base/talkgenerator.cpp b/rbutil/rbutilqt/base/talkgenerator.cpp
index 5c0f8e985b..bc7e5f18b0 100644
--- a/rbutil/rbutilqt/base/talkgenerator.cpp
+++ b/rbutil/rbutilqt/base/talkgenerator.cpp
@@ -22,7 +22,7 @@
22#include "systeminfo.h" 22#include "systeminfo.h"
23#include "wavtrim.h" 23#include "wavtrim.h"
24 24
25TalkGenerator::TalkGenerator(QObject* parent): QObject(parent) 25TalkGenerator::TalkGenerator(QObject* parent): QObject(parent), encFutureWatcher(this), ttsFutureWatcher(this)
26{ 26{
27 27
28} 28}
@@ -31,7 +31,6 @@ TalkGenerator::TalkGenerator(QObject* parent): QObject(parent)
31//! 31//!
32TalkGenerator::Status TalkGenerator::process(QList<TalkEntry>* list,int wavtrimth) 32TalkGenerator::Status TalkGenerator::process(QList<TalkEntry>* list,int wavtrimth)
33{ 33{
34 m_abort = false;
35 QString errStr; 34 QString errStr;
36 bool warnings = false; 35 bool warnings = false;
37 36
@@ -104,136 +103,179 @@ TalkGenerator::Status TalkGenerator::process(QList<TalkEntry>* list,int wavtrimt
104//! 103//!
105TalkGenerator::Status TalkGenerator::voiceList(QList<TalkEntry>* list,int wavtrimth) 104TalkGenerator::Status TalkGenerator::voiceList(QList<TalkEntry>* list,int wavtrimth)
106{ 105{
107 int progressMax = list->size(); 106 emit logProgress(0, list->size());
108 int m_progress = 0;
109 emit logProgress(m_progress,progressMax);
110 107
111 QStringList errors; 108 QStringList duplicates;
112 QStringList dublicates;
113 109
114 bool warnings = false; 110 m_ttsWarnings = false;
115 for(int i=0; i < list->size(); i++) 111 for(int i=0; i < list->size(); i++)
116 { 112 {
117 if(m_abort) 113 (*list)[i].refs.tts = m_tts;
118 { 114 (*list)[i].refs.wavtrim = wavtrimth;
119 emit logItem(tr("Voicing aborted"), LOGERROR); 115 (*list)[i].refs.generator = this;
120 return eERROR;
121 }
122 116
123 // skip dublicated wav entrys 117 // skip duplicated wav entries
124 if(!dublicates.contains(list->at(i).wavfilename)) 118 if(!duplicates.contains(list->at(i).wavfilename))
125 dublicates.append(list->at(i).wavfilename); 119 duplicates.append(list->at(i).wavfilename);
126 else 120 else
127 { 121 {
128 qDebug() << "dublicate skipped"; 122 qDebug() << "[TalkGen] duplicate skipped";
129 (*list)[i].voiced = true; 123 (*list)[i].voiced = true;
130 emit logProgress(++m_progress,progressMax);
131 continue; 124 continue;
132 } 125 }
126 }
133 127
134 // skip already voiced entrys 128 /* If the engine can't be parallelized, we use only 1 thread */
135 if(list->at(i).voiced == true) 129 int maxThreadCount = QThreadPool::globalInstance()->maxThreadCount();
136 { 130 if ((m_tts->capabilities() & TTSBase::RunInParallel) == 0)
137 emit logProgress(++m_progress,progressMax); 131 QThreadPool::globalInstance()->setMaxThreadCount(1);
138 continue; 132
139 } 133 connect(&ttsFutureWatcher, SIGNAL(progressValueChanged(int)),
140 // skip entry whith empty text 134 this, SLOT(ttsProgress(int)));
141 if(list->at(i).toSpeak == "") 135 ttsFutureWatcher.setFuture(QtConcurrent::map(*list, &TalkGenerator::ttsEntryPoint));
142 { 136
143 emit logProgress(++m_progress,progressMax); 137 /* We use this loop as an equivalent to ttsFutureWatcher.waitForFinished()
144 continue; 138 * since the latter blocks all events */
145 } 139 while(ttsFutureWatcher.isRunning())
140 QCoreApplication::processEvents();
141
142 /* Restore global settings, if we changed them */
143 if ((m_tts->capabilities() & TTSBase::RunInParallel) == 0)
144 QThreadPool::globalInstance()->setMaxThreadCount(maxThreadCount);
145
146 if(ttsFutureWatcher.isCanceled())
147 return eERROR;
148 else if(m_ttsWarnings)
149 return eWARNING;
150 else
151 return eOK;
152}
146 153
147 // voice entry 154void TalkGenerator::ttsEntryPoint(TalkEntry& entry)
155{
156 if (!entry.voiced && !entry.toSpeak.isEmpty())
157 {
148 QString error; 158 QString error;
149 qDebug() << "voicing: " << list->at(i).toSpeak << "to" << list->at(i).wavfilename; 159 qDebug() << "[TalkGen] voicing: " << entry.toSpeak << "to" << entry.wavfilename;
150 TTSStatus status = m_tts->voice(list->at(i).toSpeak,list->at(i).wavfilename, &error); 160 TTSStatus status = entry.refs.tts->voice(entry.toSpeak,entry.wavfilename, &error);
151 if(status == Warning) 161 if (status == Warning || status == FatalError)
152 { 162 {
153 warnings = true; 163 entry.refs.generator->ttsFailEntry(entry, status, error);
154 emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error), 164 return;
155 LOGWARNING);
156 } 165 }
157 else if (status == FatalError) 166 if (entry.refs.wavtrim != -1)
158 {
159 emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error),
160 LOGERROR);
161 return eERROR;
162 }
163 else
164 (*list)[i].voiced = true;
165
166 //wavetrim if needed
167 if(wavtrimth != -1)
168 { 167 {
169 char buffer[255]; 168 char buffer[255];
170 wavtrim(list->at(i).wavfilename.toLocal8Bit().data(),wavtrimth,buffer,255); 169 wavtrim(entry.wavfilename.toLocal8Bit().data(), entry.refs.wavtrim, buffer, 255);
171 } 170 }
171 entry.voiced = true;
172 }
173}
172 174
173 emit logProgress(++m_progress,progressMax); 175void TalkGenerator::ttsFailEntry(const TalkEntry& entry, TTSStatus status, QString error)
174 QCoreApplication::processEvents(); 176{
177 if(status == Warning)
178 {
179 m_ttsWarnings = true;
180 emit logItem(tr("Voicing of %1 failed: %2").arg(entry.toSpeak).arg(error),
181 LOGWARNING);
182 }
183 else if (status == FatalError)
184 {
185 emit logItem(tr("Voicing of %1 failed: %2").arg(entry.toSpeak).arg(error),
186 LOGERROR);
187 abort();
175 } 188 }
176 if(warnings)
177 return eWARNING;
178 else
179 return eOK;
180} 189}
181 190
191void TalkGenerator::ttsProgress(int value)
192{
193 emit logProgress(value,ttsFutureWatcher.progressMaximum());
194}
182 195
183//! \brief Encodes a List of strings 196//! \brief Encodes a List of strings
184//! 197//!
185TalkGenerator::Status TalkGenerator::encodeList(QList<TalkEntry>* list) 198TalkGenerator::Status TalkGenerator::encodeList(QList<TalkEntry>* list)
186{ 199{
187 QStringList dublicates; 200 QStringList duplicates;
188 201
189 int progressMax = list->size(); 202 int itemsCount = list->size();
190 int m_progress = 0; 203 emit logProgress(0, itemsCount);
191 emit logProgress(m_progress,progressMax);
192 204
193 for(int i=0; i < list->size(); i++) 205 /* Do some preprocessing and remove entries that have not been voiced. */
206 for (int idx=0; idx < itemsCount; idx++)
194 { 207 {
195 if(m_abort) 208 if(list->at(idx).voiced == false)
196 {
197 emit logItem(tr("Encoding aborted"), LOGERROR);
198 return eERROR;
199 }
200
201 //skip non-voiced entrys
202 if(list->at(i).voiced == false)
203 { 209 {
204 qDebug() << "non voiced entry" << list->at(i).toSpeak <<"detected"; 210 qDebug() << "[TalkGen] unvoiced entry" << list->at(idx).toSpeak <<"detected";
205 emit logProgress(++m_progress,progressMax); 211 list->removeAt(idx);
212 itemsCount--;
213 idx--;
206 continue; 214 continue;
207 } 215 }
208 //skip dublicates 216 if(duplicates.contains(list->at(idx).talkfilename))
209 if(!dublicates.contains(list->at(i).talkfilename))
210 dublicates.append(list->at(i).talkfilename);
211 else
212 { 217 {
213 qDebug() << "dublicate skipped"; 218 (*list)[idx].encoded = true; /* make sure we skip this entry */
214 (*list)[i].encoded = true;
215 emit logProgress(++m_progress,progressMax);
216 continue; 219 continue;
217 } 220 }
221 duplicates.append(list->at(idx).talkfilename);
222 (*list)[idx].refs.encoder = m_enc;
223 (*list)[idx].refs.generator = this; /* not really needed, unless we end up
224 voicing and encoding with two different
225 TalkGenerators.*/
226 }
218 227
219 //encode entry 228 connect(&encFutureWatcher, SIGNAL(progressValueChanged(int)),
220 qDebug() << "encoding " << list->at(i).wavfilename << "to" << list->at(i).talkfilename; 229 this, SLOT(encProgress(int)));
221 if(!m_enc->encode(list->at(i).wavfilename,list->at(i).talkfilename)) 230 encFutureWatcher.setFuture(QtConcurrent::map(*list, &TalkGenerator::encEntryPoint));
222 { 231
223 emit logItem(tr("Encoding of %1 failed").arg(list->at(i).wavfilename), LOGERROR); 232 /* We use this loop as an equivalent to encFutureWatcher.waitForFinished()
224 return eERROR; 233 * since the latter blocks all events */
234 while (encFutureWatcher.isRunning())
235 QCoreApplication::processEvents(QEventLoop::AllEvents);
236
237 if (encFutureWatcher.isCanceled())
238 return eERROR;
239 else
240 return eOK;
241}
242
243void TalkGenerator::encEntryPoint(TalkEntry& entry)
244{
245 if(!entry.encoded)
246 {
247 bool res = entry.refs.encoder->encode(entry.wavfilename, entry.talkfilename);
248 entry.encoded = res;
249 if (!entry.encoded)
250 entry.refs.generator->encFailEntry(entry);
225 } 251 }
226 (*list)[i].encoded = true; 252 return;
227 emit logProgress(++m_progress,progressMax); 253}
228 QCoreApplication::processEvents(); 254
229 } 255void TalkGenerator::encProgress(int value)
230 return eOK; 256{
257 emit logProgress(value, encFutureWatcher.progressMaximum());
258}
259
260void TalkGenerator::encFailEntry(const TalkEntry& entry)
261{
262 emit logItem(tr("Encoding of %1 failed").arg(entry.wavfilename), LOGERROR);
263 abort();
231} 264}
232 265
233//! \brief slot, which is connected to the abort of the Logger. Sets a flag, so Creating Talkfiles ends at the next possible position 266//! \brief slot, which is connected to the abort of the Logger. Sets a flag, so Creating Talkfiles ends at the next possible position
234//! 267//!
235void TalkGenerator::abort() 268void TalkGenerator::abort()
236{ 269{
237 m_abort = true; 270 if (ttsFutureWatcher.isRunning())
271 {
272 ttsFutureWatcher.cancel();
273 emit logItem(tr("Voicing aborted"), LOGERROR);
274 }
275 if (encFutureWatcher.isRunning())
276 {
277 encFutureWatcher.cancel();
278 emit logItem(tr("Encoding aborted"), LOGERROR);
279 }
238} 280}
239 281