Handle language change events in widgets.
[maemo-rb.git] / rbutil / rbutilqt / base / ttssapi.cpp
blobf726dcf8dad9a11b515be71ef4342c72cd12aa48
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 "ttssapi.h"
20 #include "utils.h"
21 #include "rbsettings.h"
22 #include "systeminfo.h"
24 TTSSapi::TTSSapi(QObject* parent) : TTSBase(parent)
26 m_TTSTemplate = "cscript //nologo \"%exe\" /language:%lang /voice:\"%voice\""
27 " /speed:%speed \"%options\"";
28 defaultLanguage = "english";
29 m_sapi4 = false;
30 m_started = false;
33 TTSBase::Capabilities TTSSapi::capabilities()
35 return None;
38 void TTSSapi::generateSettings()
40 // language
41 QMap<QString, QStringList> languages = SystemInfo::languages();
42 QStringList langs;
43 for(int i = 0; i < languages.values().size(); ++i) {
44 langs.append(languages.values().at(i).at(0));
46 EncTtsSetting* setting =new EncTtsSetting(this,EncTtsSetting::eSTRINGLIST,
47 tr("Language:"),RbSettings::subValue("sapi",RbSettings::TtsLanguage),
48 langs);
49 connect(setting,SIGNAL(dataChanged()),this,SLOT(updateVoiceList()));
50 insertSetting(eLANGUAGE,setting);
51 // voice
52 setting = new EncTtsSetting(this,EncTtsSetting::eSTRINGLIST,
53 tr("Voice:"),RbSettings::subValue("sapi",RbSettings::TtsVoice),
54 getVoiceList(RbSettings::subValue("sapi",RbSettings::TtsLanguage).toString()),
55 EncTtsSetting::eREFRESHBTN);
56 connect(setting,SIGNAL(refresh()),this,SLOT(updateVoiceList()));
57 insertSetting(eVOICE,setting);
58 //speed
59 int speed = RbSettings::subValue("sapi", RbSettings::TtsSpeed).toInt();
60 if(speed > 10 || speed < -10)
61 speed = 0;
62 insertSetting(eSPEED, new EncTtsSetting(this, EncTtsSetting::eINT,
63 tr("Speed:"), speed, -10, 10));
64 // options
65 insertSetting(eOPTIONS,new EncTtsSetting(this,EncTtsSetting::eSTRING,
66 tr("Options:"),RbSettings::subValue("sapi",RbSettings::TtsOptions)));
70 void TTSSapi::saveSettings()
72 //save settings in user config
73 RbSettings::setSubValue("sapi",RbSettings::TtsLanguage,
74 getSetting(eLANGUAGE)->current().toString());
75 RbSettings::setSubValue("sapi",RbSettings::TtsVoice,
76 getSetting(eVOICE)->current().toString());
77 RbSettings::setSubValue("sapi",RbSettings::TtsSpeed,
78 getSetting(eSPEED)->current().toInt());
79 RbSettings::setSubValue("sapi",RbSettings::TtsOptions,
80 getSetting(eOPTIONS)->current().toString());
82 RbSettings::sync();
85 void TTSSapi::updateVoiceList()
87 qDebug() << "[TTSSapi] updating voicelist";
88 QStringList voiceList = getVoiceList(getSetting(eLANGUAGE)->current().toString());
89 getSetting(eVOICE)->setList(voiceList);
90 if(voiceList.size() > 0) getSetting(eVOICE)->setCurrent(voiceList.at(0));
91 else getSetting(eVOICE)->setCurrent("");
94 bool TTSSapi::start(QString *errStr)
97 m_TTSOpts = RbSettings::subValue("sapi",RbSettings::TtsOptions).toString();
98 m_TTSLanguage =RbSettings::subValue("sapi",RbSettings::TtsLanguage).toString();
99 m_TTSVoice=RbSettings::subValue("sapi",RbSettings::TtsVoice).toString();
100 m_TTSSpeed=RbSettings::subValue("sapi",RbSettings::TtsSpeed).toString();
101 m_sapi4 = RbSettings::subValue("sapi",RbSettings::TtsUseSapi4).toBool();
103 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
104 QFile::copy(":/builtin/sapi_voice.vbs",QDir::tempPath() + "/sapi_voice.vbs");
105 m_TTSexec = QDir::tempPath() +"/sapi_voice.vbs";
107 QFileInfo tts(m_TTSexec);
108 if(!tts.exists())
110 *errStr = tr("Could not copy the SAPI script");
111 return false;
113 // create the voice process
114 QString execstring = m_TTSTemplate;
115 execstring.replace("%exe",m_TTSexec);
116 execstring.replace("%options",m_TTSOpts);
117 execstring.replace("%lang",m_TTSLanguage);
118 execstring.replace("%voice",m_TTSVoice);
119 execstring.replace("%speed",m_TTSSpeed);
121 if(m_sapi4)
122 execstring.append(" /sapi4 ");
124 qDebug() << "[TTSSapi] Start:" << execstring;
125 voicescript = new QProcess(NULL);
126 //connect(voicescript,SIGNAL(readyReadStandardError()),this,SLOT(error()));
127 voicescript->start(execstring);
128 qDebug() << "[TTSSapi] wait for process";
129 if(!voicescript->waitForStarted())
131 *errStr = tr("Could not start SAPI process");
132 qDebug() << "[TTSSapi] starting process timed out!";
133 return false;
136 if(!voicescript->waitForReadyRead(300))
138 *errStr = voicescript->readAllStandardError();
139 if(*errStr != "")
140 return false;
143 voicestream = new QTextStream(voicescript);
144 voicestream->setCodec("UTF16-LE");
146 m_started = true;
147 return true;
150 QString TTSSapi::voiceVendor(void)
152 bool keeprunning = m_started;
153 QString vendor;
154 if(!m_started) {
155 QString error;
156 start(&error);
158 *voicestream << "QUERY\tVENDOR\r\n";
159 voicestream->flush();
160 while((vendor = voicestream->readLine()).isEmpty())
161 QCoreApplication::processEvents();
163 qDebug() << "[TTSSAPI] TTS vendor:" << vendor;
164 if(!keeprunning) {
165 stop();
167 return vendor;
170 QStringList TTSSapi::getVoiceList(QString language)
172 QStringList result;
174 QFile::copy(":/builtin/sapi_voice.vbs",QDir::tempPath() + "/sapi_voice.vbs");
175 m_TTSexec = QDir::tempPath() +"/sapi_voice.vbs";
177 QFileInfo tts(m_TTSexec);
178 if(!tts.exists())
179 return result;
181 // create the voice process
182 QString execstring = "cscript //nologo \"%exe\" /language:%lang /listvoices";
183 execstring.replace("%exe",m_TTSexec);
184 execstring.replace("%lang",language);
186 if(RbSettings::value(RbSettings::TtsUseSapi4).toBool())
187 execstring.append(" /sapi4 ");
189 qDebug() << "[TTSSapi] Start:" << execstring;
190 voicescript = new QProcess(NULL);
191 voicescript->start(execstring);
192 qDebug() << "[TTSSapi] wait for process";
193 if(!voicescript->waitForStarted()) {
194 qDebug() << "[TTSSapi] process startup timed out!";
195 return result;
197 voicescript->closeWriteChannel();
198 voicescript->waitForReadyRead();
200 QString dataRaw = voicescript->readAllStandardError().data();
201 result = dataRaw.split(",",QString::SkipEmptyParts);
202 if(result.size() > 0)
204 result.sort();
205 result.removeFirst();
206 for(int i = 0; i< result.size();i++)
208 result[i] = result.at(i).simplified();
212 delete voicescript;
213 QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",
214 QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner
215 | QFile::ReadUser | QFile::WriteUser | QFile::ExeUser
216 | QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup
217 | QFile::ReadOther | QFile::WriteOther | QFile::ExeOther );
218 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
219 return result;
224 TTSStatus TTSSapi::voice(QString text,QString wavfile, QString *errStr)
226 (void) errStr;
227 QString query = "SPEAK\t"+wavfile+"\t"+text;
228 qDebug() << "[TTSSapi] voicing" << query;
229 // append newline to query. Done now to keep debug output more readable.
230 query.append("\r\n");
231 *voicestream << query;
232 *voicestream << "SYNC\tbla\r\n";
233 voicestream->flush();
234 // do NOT poll the output with readLine(), this causes sync issues!
235 voicescript->waitForReadyRead();
237 if(!QFileInfo(wavfile).isFile()) {
238 qDebug() << "[TTSSapi] output file does not exist:" << wavfile;
239 return FatalError;
241 return NoError;
244 bool TTSSapi::stop()
246 *voicestream << "QUIT\r\n";
247 voicestream->flush();
248 voicescript->waitForFinished();
249 delete voicestream;
250 delete voicescript;
251 QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",
252 QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner
253 | QFile::ReadUser | QFile::WriteUser | QFile::ExeUser
254 | QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup
255 | QFile::ReadOther | QFile::WriteOther | QFile::ExeOther );
256 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
257 m_started = false;
258 return true;
261 bool TTSSapi::configOk()
263 if(RbSettings::subValue("sapi",RbSettings::TtsVoice).toString().isEmpty())
264 return false;
265 return true;