1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2007 by Dominik Wenger
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
22 #include "rbsettings.h"
23 #include "systeminfo.h"
25 TTSSapi::TTSSapi(QObject
* parent
) : TTSBase(parent
)
27 m_TTSTemplate
= "cscript //nologo \"%exe\" /language:%lang /voice:\"%voice\""
28 " /speed:%speed \"%options\"";
29 defaultLanguage
="english";
33 TTSBase::Capabilities
TTSSapi::capabilities()
38 void TTSSapi::generateSettings()
41 QMap
<QString
, QString
> languages
= SystemInfo::languages();
42 EncTtsSetting
* setting
=new EncTtsSetting(this,EncTtsSetting::eSTRINGLIST
,
43 tr("Language:"),RbSettings::subValue("sapi",RbSettings::TtsLanguage
),
45 connect(setting
,SIGNAL(dataChanged()),this,SLOT(updateVoiceList()));
46 insertSetting(eLANGUAGE
,setting
);
48 setting
= new EncTtsSetting(this,EncTtsSetting::eSTRINGLIST
,
49 tr("Voice:"),RbSettings::subValue("sapi",RbSettings::TtsVoice
),
50 getVoiceList(RbSettings::subValue("sapi",RbSettings::TtsLanguage
).toString()),
51 EncTtsSetting::eREFRESHBTN
);
52 connect(setting
,SIGNAL(refresh()),this,SLOT(updateVoiceList()));
53 insertSetting(eVOICE
,setting
);
55 int speed
= RbSettings::subValue("sapi", RbSettings::TtsSpeed
).toInt();
56 if(speed
> 10 || speed
< -10)
58 insertSetting(eSPEED
, new EncTtsSetting(this, EncTtsSetting::eINT
,
59 tr("Speed:"), speed
, -10, 10));
61 insertSetting(eOPTIONS
,new EncTtsSetting(this,EncTtsSetting::eSTRING
,
62 tr("Options:"),RbSettings::subValue("sapi",RbSettings::TtsOptions
)));
66 void TTSSapi::saveSettings()
68 //save settings in user config
69 RbSettings::setSubValue("sapi",RbSettings::TtsLanguage
,
70 getSetting(eLANGUAGE
)->current().toString());
71 RbSettings::setSubValue("sapi",RbSettings::TtsVoice
,
72 getSetting(eVOICE
)->current().toString());
73 RbSettings::setSubValue("sapi",RbSettings::TtsSpeed
,
74 getSetting(eSPEED
)->current().toInt());
75 RbSettings::setSubValue("sapi",RbSettings::TtsOptions
,
76 getSetting(eOPTIONS
)->current().toString());
81 void TTSSapi::updateVoiceList()
83 qDebug() << "update voiceList";
84 QStringList voiceList
= getVoiceList(getSetting(eLANGUAGE
)->current().toString());
85 getSetting(eVOICE
)->setList(voiceList
);
86 if(voiceList
.size() > 0) getSetting(eVOICE
)->setCurrent(voiceList
.at(0));
87 else getSetting(eVOICE
)->setCurrent("");
90 bool TTSSapi::start(QString
*errStr
)
93 m_TTSOpts
= RbSettings::subValue("sapi",RbSettings::TtsOptions
).toString();
94 m_TTSLanguage
=RbSettings::subValue("sapi",RbSettings::TtsLanguage
).toString();
95 m_TTSVoice
=RbSettings::subValue("sapi",RbSettings::TtsVoice
).toString();
96 m_TTSSpeed
=RbSettings::subValue("sapi",RbSettings::TtsSpeed
).toString();
97 m_sapi4
= RbSettings::subValue("sapi",RbSettings::TtsUseSapi4
).toBool();
99 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
100 QFile::copy(":/builtin/sapi_voice.vbs",QDir::tempPath() + "/sapi_voice.vbs");
101 m_TTSexec
= QDir::tempPath() +"/sapi_voice.vbs";
103 QFileInfo
tts(m_TTSexec
);
106 *errStr
= tr("Could not copy the Sapi-script");
109 // create the voice process
110 QString execstring
= m_TTSTemplate
;
111 execstring
.replace("%exe",m_TTSexec
);
112 execstring
.replace("%options",m_TTSOpts
);
113 execstring
.replace("%lang",m_TTSLanguage
);
114 execstring
.replace("%voice",m_TTSVoice
);
115 execstring
.replace("%speed",m_TTSSpeed
);
118 execstring
.append(" /sapi4 ");
120 qDebug() << "init" << execstring
;
121 voicescript
= new QProcess(NULL
);
122 //connect(voicescript,SIGNAL(readyReadStandardError()),this,SLOT(error()));
124 voicescript
->start(execstring
);
125 if(!voicescript
->waitForStarted())
127 *errStr
= tr("Could not start the Sapi-script");
131 if(!voicescript
->waitForReadyRead(300))
133 *errStr
= voicescript
->readAllStandardError();
138 voicestream
= new QTextStream(voicescript
);
139 voicestream
->setCodec("UTF16-LE");
145 QStringList
TTSSapi::getVoiceList(QString language
)
149 QFile::copy(":/builtin/sapi_voice.vbs",QDir::tempPath() + "/sapi_voice.vbs");
150 m_TTSexec
= QDir::tempPath() +"/sapi_voice.vbs";
152 QFileInfo
tts(m_TTSexec
);
156 // create the voice process
157 QString execstring
= "cscript //nologo \"%exe\" /language:%lang /listvoices";
158 execstring
.replace("%exe",m_TTSexec
);
159 execstring
.replace("%lang",language
);
161 if(RbSettings::value(RbSettings::TtsUseSapi4
).toBool())
162 execstring
.append(" /sapi4 ");
164 qDebug() << "init" << execstring
;
165 voicescript
= new QProcess(NULL
);
166 voicescript
->start(execstring
);
167 qDebug() << "wait for started";
168 if(!voicescript
->waitForStarted())
170 voicescript
->closeWriteChannel();
171 voicescript
->waitForReadyRead();
173 QString dataRaw
= voicescript
->readAllStandardError().data();
174 result
= dataRaw
.split(",",QString::SkipEmptyParts
);
175 if(result
.size() > 0)
178 result
.removeFirst();
179 for(int i
= 0; i
< result
.size();i
++)
181 result
[i
] = result
.at(i
).simplified();
186 QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",
187 QFile::ReadOwner
| QFile::WriteOwner
| QFile::ExeOwner
188 | QFile::ReadUser
| QFile::WriteUser
| QFile::ExeUser
189 | QFile::ReadGroup
| QFile::WriteGroup
| QFile::ExeGroup
190 | QFile::ReadOther
| QFile::WriteOther
| QFile::ExeOther
);
191 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
197 TTSStatus
TTSSapi::voice(QString text
,QString wavfile
, QString
*errStr
)
200 QString query
= "SPEAK\t"+wavfile
+"\t"+text
;
201 qDebug() << "[TTSSapi] voicing" << query
;
202 // append newline to query. Done now to keep debug output more readable.
203 query
.append("\r\n");
204 *voicestream
<< query
;
205 *voicestream
<< "SYNC\tbla\r\n";
206 voicestream
->flush();
209 //we use this, because waitForReadyRead doesnt work from a different thread
210 while( voicescript
->readLine(temp
,20) == 0)
211 QCoreApplication::processEvents();
218 *voicestream
<< "QUIT\r\n";
219 voicestream
->flush();
220 voicescript
->waitForFinished();
223 QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",
224 QFile::ReadOwner
| QFile::WriteOwner
| QFile::ExeOwner
225 | QFile::ReadUser
| QFile::WriteUser
| QFile::ExeUser
226 | QFile::ReadGroup
| QFile::WriteGroup
| QFile::ExeGroup
227 | QFile::ReadOther
| QFile::WriteOther
| QFile::ExeOther
);
228 QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
232 bool TTSSapi::configOk()
234 if(RbSettings::subValue("sapi",RbSettings::TtsVoice
).toString().isEmpty())