summaryrefslogtreecommitdiff
path: root/rbutil/rbutilqt
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil/rbutilqt')
-rw-r--r--rbutil/rbutilqt/base/encoders.cpp10
-rw-r--r--rbutil/rbutilqt/base/talkgenerator.cpp220
-rw-r--r--rbutil/rbutilqt/base/talkgenerator.h27
-rw-r--r--rbutil/rbutilqt/base/ttsbase.h12
-rw-r--r--rbutil/rbutilqt/base/ttscarbon.cpp4
-rw-r--r--rbutil/rbutilqt/base/ttscarbon.h2
-rw-r--r--rbutil/rbutilqt/base/ttsexes.cpp5
-rw-r--r--rbutil/rbutilqt/base/ttsexes.h1
-rw-r--r--rbutil/rbutilqt/base/ttsfestival.cpp5
-rw-r--r--rbutil/rbutilqt/base/ttsfestival.h1
-rw-r--r--rbutil/rbutilqt/base/ttssapi.cpp13
-rw-r--r--rbutil/rbutilqt/base/ttssapi.h1
12 files changed, 197 insertions, 104 deletions
diff --git a/rbutil/rbutilqt/base/encoders.cpp b/rbutil/rbutilqt/base/encoders.cpp
index 3b9e1432ed..d763b96b4b 100644
--- a/rbutil/rbutilqt/base/encoders.cpp
+++ b/rbutil/rbutilqt/base/encoders.cpp
@@ -131,7 +131,7 @@ bool EncExes::encode(QString input,QString output)
131 execstring.replace("%options",m_EncOpts); 131 execstring.replace("%options",m_EncOpts);
132 execstring.replace("%input",input); 132 execstring.replace("%input",input);
133 execstring.replace("%output",output); 133 execstring.replace("%output",output);
134 qDebug() << execstring; 134 qDebug() << "[EncExes] cmd: " << execstring;
135 int result = QProcess::execute(execstring); 135 int result = QProcess::execute(execstring);
136 return (result == 0) ? true : false; 136 return (result == 0) ? true : false;
137} 137}
@@ -197,16 +197,16 @@ bool EncRbSpeex::start()
197 197
198bool EncRbSpeex::encode(QString input,QString output) 198bool EncRbSpeex::encode(QString input,QString output)
199{ 199{
200 qDebug() << "encoding " << input << " to "<< output; 200 qDebug() << "[RbSpeex] Encoding " << input << " to "<< output;
201 char errstr[512]; 201 char errstr[512];
202 202
203 FILE *fin,*fout; 203 FILE *fin,*fout;
204 if ((fin = fopen(input.toLocal8Bit(), "rb")) == NULL) { 204 if ((fin = fopen(input.toLocal8Bit(), "rb")) == NULL) {
205 qDebug() << "Error: could not open input file\n"; 205 qDebug() << "[RbSpeex] Error: could not open input file\n";
206 return false; 206 return false;
207 } 207 }
208 if ((fout = fopen(output.toLocal8Bit(), "wb")) == NULL) { 208 if ((fout = fopen(output.toLocal8Bit(), "wb")) == NULL) {
209 qDebug() << "Error: could not open output file\n"; 209 qDebug() << "[RbSpeex] Error: could not open output file\n";
210 fclose(fin); 210 fclose(fin);
211 return false; 211 return false;
212 } 212 }
@@ -218,7 +218,7 @@ bool EncRbSpeex::encode(QString input,QString output)
218 218
219 if (!ret) { 219 if (!ret) {
220 /* Attempt to delete unfinished output */ 220 /* Attempt to delete unfinished output */
221 qDebug() << "Error:" << errstr; 221 qDebug() << "[RbSpeex] Error:" << errstr;
222 QFile(output).remove(); 222 QFile(output).remove();
223 return false; 223 return false;
224 } 224 }
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
diff --git a/rbutil/rbutilqt/base/talkgenerator.h b/rbutil/rbutilqt/base/talkgenerator.h
index b139c1879b..cca196bc2e 100644
--- a/rbutil/rbutilqt/base/talkgenerator.h
+++ b/rbutil/rbutilqt/base/talkgenerator.h
@@ -49,14 +49,29 @@ public:
49 QString target; 49 QString target;
50 bool voiced; 50 bool voiced;
51 bool encoded; 51 bool encoded;
52
53 /* We need the following members because
54 * 1) the QtConcurrent entry points are all static methods (and we
55 * need to communicate with the TalkGenerator)
56 * 2) we are not guaranteed to go through the list in any
57 * particular order, so we can't use the progress slot
58 * for error checking */
59 struct
60 {
61 EncBase* encoder;
62 TTSBase* tts;
63 TalkGenerator* generator;
64 int wavtrim;
65 } refs;
52 }; 66 };
53 67
54 TalkGenerator(QObject* parent); 68 TalkGenerator(QObject* parent);
55
56 Status process(QList<TalkEntry>* list,int wavtrimth = -1); 69 Status process(QList<TalkEntry>* list,int wavtrimth = -1);
57 70
58public slots: 71public slots:
59 void abort(); 72 void abort();
73 void encProgress(int value);
74 void ttsProgress(int value);
60 75
61signals: 76signals:
62 void done(bool); 77 void done(bool);
@@ -64,13 +79,21 @@ signals:
64 void logProgress(int, int); //! set progress bar. 79 void logProgress(int, int); //! set progress bar.
65 80
66private: 81private:
82 QFutureWatcher<void> encFutureWatcher;
83 QFutureWatcher<void> ttsFutureWatcher;
84 void encFailEntry(const TalkEntry& entry);
85 void ttsFailEntry(const TalkEntry& entry, TTSStatus status, QString error);
86
67 Status voiceList(QList<TalkEntry>* list,int wavetrimth); 87 Status voiceList(QList<TalkEntry>* list,int wavetrimth);
68 Status encodeList(QList<TalkEntry>* list); 88 Status encodeList(QList<TalkEntry>* list);
69 89
90 static void encEntryPoint(TalkEntry& entry);
91 static void ttsEntryPoint(TalkEntry& entry);
92
70 TTSBase* m_tts; 93 TTSBase* m_tts;
71 EncBase* m_enc; 94 EncBase* m_enc;
72 95
73 bool m_abort; 96 bool m_ttsWarnings;
74}; 97};
75 98
76 99
diff --git a/rbutil/rbutilqt/base/ttsbase.h b/rbutil/rbutilqt/base/ttsbase.h
index 7c5932401f..f04016c85f 100644
--- a/rbutil/rbutilqt/base/ttsbase.h
+++ b/rbutil/rbutilqt/base/ttsbase.h
@@ -32,11 +32,13 @@
32#include "encttssettings.h" 32#include "encttssettings.h"
33 33
34enum TTSStatus{ FatalError, NoError, Warning }; 34enum TTSStatus{ FatalError, NoError, Warning };
35
36class TTSBase : public EncTtsSettingInterface 35class TTSBase : public EncTtsSettingInterface
37{ 36{
38 Q_OBJECT 37 Q_OBJECT
39 public: 38 public:
39 enum Capability { None = 0, RunInParallel = 1 };
40 Q_DECLARE_FLAGS(Capabilities, Capability)
41
40 TTSBase(QObject *parent); 42 TTSBase(QObject *parent);
41 //! Child class should generate a clip 43 //! Child class should generate a clip
42 virtual TTSStatus voice(QString text,QString wavfile, QString* errStr) =0; 44 virtual TTSStatus voice(QString text,QString wavfile, QString* errStr) =0;
@@ -53,6 +55,8 @@ class TTSBase : public EncTtsSettingInterface
53 //! Chlid class should commit the Settings to permanent storage 55 //! Chlid class should commit the Settings to permanent storage
54 virtual void saveSettings() = 0; 56 virtual void saveSettings() = 0;
55 57
58 virtual Capabilities capabilities() = 0;
59
56 // static functions 60 // static functions
57 static TTSBase* getTTS(QObject* parent,QString ttsname); 61 static TTSBase* getTTS(QObject* parent,QString ttsname);
58 static QStringList getTTSList(); 62 static QStringList getTTSList();
@@ -65,10 +69,6 @@ class TTSBase : public EncTtsSettingInterface
65 protected: 69 protected:
66 static QMap<QString,QString> ttsList; 70 static QMap<QString,QString> ttsList;
67}; 71};
68 72Q_DECLARE_OPERATORS_FOR_FLAGS(TTSBase::Capabilities)
69
70
71
72
73 73
74#endif 74#endif
diff --git a/rbutil/rbutilqt/base/ttscarbon.cpp b/rbutil/rbutilqt/base/ttscarbon.cpp
index f2e0b7dba3..63fb5315e3 100644
--- a/rbutil/rbutilqt/base/ttscarbon.cpp
+++ b/rbutil/rbutilqt/base/ttscarbon.cpp
@@ -34,6 +34,10 @@ TTSCarbon::TTSCarbon(QObject* parent) : TTSBase(parent)
34{ 34{
35} 35}
36 36
37TTSBase::Capabilities TTSCarbon::capabilities()
38{
39 return None;
40}
37 41
38bool TTSCarbon::configOk() 42bool TTSCarbon::configOk()
39{ 43{
diff --git a/rbutil/rbutilqt/base/ttscarbon.h b/rbutil/rbutilqt/base/ttscarbon.h
index b2d39047a5..fd5f84849b 100644
--- a/rbutil/rbutilqt/base/ttscarbon.h
+++ b/rbutil/rbutilqt/base/ttscarbon.h
@@ -53,6 +53,8 @@ class TTSCarbon : public TTSBase
53 //! Chlid class should commit the Settings to permanent storage 53 //! Chlid class should commit the Settings to permanent storage
54 void saveSettings(); 54 void saveSettings();
55 55
56 Capabilities capabilities();
57
56 private: 58 private:
57 SpeechChannel m_channel; 59 SpeechChannel m_channel;
58 CFStringBuiltInEncodings m_voiceScript; 60 CFStringBuiltInEncodings m_voiceScript;
diff --git a/rbutil/rbutilqt/base/ttsexes.cpp b/rbutil/rbutilqt/base/ttsexes.cpp
index bd14e2a9ee..1818301220 100644
--- a/rbutil/rbutilqt/base/ttsexes.cpp
+++ b/rbutil/rbutilqt/base/ttsexes.cpp
@@ -31,6 +31,11 @@ TTSExes::TTSExes(QString name,QObject* parent) : TTSBase(parent)
31 31
32} 32}
33 33
34TTSBase::Capabilities TTSExes::capabilities()
35{
36 return RunInParallel;
37}
38
34void TTSExes::generateSettings() 39void TTSExes::generateSettings()
35{ 40{
36 QString exepath =RbSettings::subValue(m_name,RbSettings::TtsPath).toString(); 41 QString exepath =RbSettings::subValue(m_name,RbSettings::TtsPath).toString();
diff --git a/rbutil/rbutilqt/base/ttsexes.h b/rbutil/rbutilqt/base/ttsexes.h
index c03beb7595..04efb4ce50 100644
--- a/rbutil/rbutilqt/base/ttsexes.h
+++ b/rbutil/rbutilqt/base/ttsexes.h
@@ -38,6 +38,7 @@ class TTSExes : public TTSBase
38 TTSStatus voice(QString text, QString wavfile, QString *errStr); 38 TTSStatus voice(QString text, QString wavfile, QString *errStr);
39 bool start(QString *errStr); 39 bool start(QString *errStr);
40 bool stop() {return true;} 40 bool stop() {return true;}
41 Capabilities capabilities();
41 42
42 // for settings 43 // for settings
43 void generateSettings(); 44 void generateSettings();
diff --git a/rbutil/rbutilqt/base/ttsfestival.cpp b/rbutil/rbutilqt/base/ttsfestival.cpp
index 7cad16d3dd..7a9c854716 100644
--- a/rbutil/rbutilqt/base/ttsfestival.cpp
+++ b/rbutil/rbutilqt/base/ttsfestival.cpp
@@ -27,6 +27,11 @@ TTSFestival::~TTSFestival()
27 stop(); 27 stop();
28} 28}
29 29
30TTSBase::Capabilities TTSFestival::capabilities()
31{
32 return RunInParallel;
33}
34
30void TTSFestival::generateSettings() 35void TTSFestival::generateSettings()
31{ 36{
32 // server path 37 // server path
diff --git a/rbutil/rbutilqt/base/ttsfestival.h b/rbutil/rbutilqt/base/ttsfestival.h
index 8a687375bc..6c64c61532 100644
--- a/rbutil/rbutilqt/base/ttsfestival.h
+++ b/rbutil/rbutilqt/base/ttsfestival.h
@@ -42,6 +42,7 @@ class TTSFestival : public TTSBase
42 bool start(QString *errStr); 42 bool start(QString *errStr);
43 bool stop(); 43 bool stop();
44 TTSStatus voice(QString text,QString wavfile, QString *errStr); 44 TTSStatus voice(QString text,QString wavfile, QString *errStr);
45 Capabilities capabilities();
45 46
46 // for settings 47 // for settings
47 bool configOk(); 48 bool configOk();
diff --git a/rbutil/rbutilqt/base/ttssapi.cpp b/rbutil/rbutilqt/base/ttssapi.cpp
index 4f69de56ae..36ce16826f 100644
--- a/rbutil/rbutilqt/base/ttssapi.cpp
+++ b/rbutil/rbutilqt/base/ttssapi.cpp
@@ -30,6 +30,11 @@ TTSSapi::TTSSapi(QObject* parent) : TTSBase(parent)
30 m_sapi4 =false; 30 m_sapi4 =false;
31} 31}
32 32
33TTSBase::Capabilities TTSSapi::capabilities()
34{
35 return None;
36}
37
33void TTSSapi::generateSettings() 38void TTSSapi::generateSettings()
34{ 39{
35 // language 40 // language
@@ -195,13 +200,17 @@ TTSStatus TTSSapi::voice(QString text,QString wavfile, QString *errStr)
195 *voicestream << query; 200 *voicestream << query;
196 *voicestream << "SYNC\tbla\r\n"; 201 *voicestream << "SYNC\tbla\r\n";
197 voicestream->flush(); 202 voicestream->flush();
198 voicescript->waitForReadyRead(); 203 char temp[20];
204
205 //we use this, because waitForReadyRead doesnt work from a different thread
206 while( voicescript->readLine(temp,20) == 0)
207 QCoreApplication::processEvents();
208
199 return NoError; 209 return NoError;
200} 210}
201 211
202bool TTSSapi::stop() 212bool TTSSapi::stop()
203{ 213{
204
205 *voicestream << "QUIT\r\n"; 214 *voicestream << "QUIT\r\n";
206 voicestream->flush(); 215 voicestream->flush();
207 voicescript->waitForFinished(); 216 voicescript->waitForFinished();
diff --git a/rbutil/rbutilqt/base/ttssapi.h b/rbutil/rbutilqt/base/ttssapi.h
index 531f25679c..6070728a79 100644
--- a/rbutil/rbutilqt/base/ttssapi.h
+++ b/rbutil/rbutilqt/base/ttssapi.h
@@ -42,6 +42,7 @@ class TTSSapi : public TTSBase
42 TTSStatus voice(QString text,QString wavfile, QString *errStr); 42 TTSStatus voice(QString text,QString wavfile, QString *errStr);
43 bool start(QString *errStr); 43 bool start(QString *errStr);
44 bool stop(); 44 bool stop();
45 Capabilities capabilities();
45 46
46 // for settings 47 // for settings
47 bool configOk(); 48 bool configOk();