diff options
Diffstat (limited to 'rbutil/rbutilqt/voicefile.cpp')
-rw-r--r-- | rbutil/rbutilqt/voicefile.cpp | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/rbutil/rbutilqt/voicefile.cpp b/rbutil/rbutilqt/voicefile.cpp new file mode 100644 index 0000000000..9390fa2fe9 --- /dev/null +++ b/rbutil/rbutilqt/voicefile.cpp | |||
@@ -0,0 +1,275 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * | ||
9 | * Copyright (C) 2007 by Dominik Wenger | ||
10 | * $Id: voicefile.h 15932 2007-12-15 13:13:57Z domonoky $ | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include "voicefile.h" | ||
21 | |||
22 | #define STATE_INVALID 0 | ||
23 | #define STATE_PHRASE 1 | ||
24 | #define STATE_VOICE 2 | ||
25 | |||
26 | |||
27 | VoiceFileCreator::VoiceFileCreator(QObject* parent) :QObject(parent) | ||
28 | { | ||
29 | |||
30 | } | ||
31 | |||
32 | void VoiceFileCreator::abort() | ||
33 | { | ||
34 | m_abort = true; | ||
35 | } | ||
36 | |||
37 | bool VoiceFileCreator::createVoiceFile(ProgressloggerInterface* logger) | ||
38 | { | ||
39 | m_abort = false; | ||
40 | m_logger = logger; | ||
41 | m_logger->addItem("Starting Voicefile generation",LOGINFO); | ||
42 | |||
43 | // test if tempdir exists | ||
44 | if(!QDir(QDir::tempPath()+"/rbvoice/").exists()) | ||
45 | { | ||
46 | QDir(QDir::tempPath()).mkdir("rbvoice"); | ||
47 | } | ||
48 | |||
49 | m_path = QDir::tempPath() + "/rbvoice/"; | ||
50 | |||
51 | // read rockbox-info.txt | ||
52 | QFile info(m_mountpoint+"/.rockbox/rockbox-info.txt"); | ||
53 | if(!info.open(QIODevice::ReadOnly)) | ||
54 | { | ||
55 | m_logger->addItem("failed to open rockbox-info.txt",LOGERROR); | ||
56 | return false; | ||
57 | } | ||
58 | |||
59 | QString target, features,version; | ||
60 | while (!info.atEnd()) { | ||
61 | QString line = info.readLine(); | ||
62 | |||
63 | if(line.contains("Target:")) | ||
64 | { | ||
65 | target = line.remove("Target:").trimmed(); | ||
66 | } | ||
67 | else if(line.contains("Features:")) | ||
68 | { | ||
69 | features = line.remove("Features:").trimmed(); | ||
70 | } | ||
71 | else if(line.contains("Version:")) | ||
72 | { | ||
73 | version = line.remove("Version:").trimmed(); | ||
74 | version = version.left(version.indexOf("-")).remove(0,1); | ||
75 | } | ||
76 | } | ||
77 | info.close(); | ||
78 | |||
79 | //prepare download url | ||
80 | QUrl genlangUrl = deviceSettings->value("genlang_url").toString() +"?lang=" +m_lang+"&t="+target+"&rev="+version+"&f="+features; | ||
81 | |||
82 | qDebug() << "downloading " << genlangUrl; | ||
83 | |||
84 | //download the correct genlang output | ||
85 | QTemporaryFile *downloadFile = new QTemporaryFile(this); | ||
86 | downloadFile->open(); | ||
87 | filename = downloadFile->fileName(); | ||
88 | downloadFile->close(); | ||
89 | // get the real file. | ||
90 | getter = new HttpGet(this); | ||
91 | getter->setProxy(m_proxy); | ||
92 | getter->setFile(downloadFile); | ||
93 | getter->getFile(genlangUrl); | ||
94 | |||
95 | connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool))); | ||
96 | connect(getter, SIGNAL(downloadDone(int, bool)), this, SLOT(downloadRequestFinished(int, bool))); | ||
97 | connect(getter, SIGNAL(dataReadProgress(int, int)), this, SLOT(updateDataReadProgress(int, int))); | ||
98 | connect(m_logger, SIGNAL(aborted()), getter, SLOT(abort())); | ||
99 | return true; | ||
100 | } | ||
101 | |||
102 | |||
103 | void VoiceFileCreator::downloadRequestFinished(int id, bool error) | ||
104 | { | ||
105 | qDebug() << "Install::downloadRequestFinished" << id << error; | ||
106 | qDebug() << "error:" << getter->errorString(); | ||
107 | |||
108 | downloadDone(error); | ||
109 | } | ||
110 | |||
111 | |||
112 | void VoiceFileCreator::downloadDone(bool error) | ||
113 | { | ||
114 | qDebug() << "Voice creator::downloadDone, error:" << error; | ||
115 | |||
116 | // update progress bar | ||
117 | int max = m_logger->getProgressMax(); | ||
118 | if(max == 0) { | ||
119 | max = 100; | ||
120 | m_logger->setProgressMax(max); | ||
121 | } | ||
122 | m_logger->setProgressValue(max); | ||
123 | if(getter->httpResponse() != 200 && !getter->isCached()) { | ||
124 | m_logger->addItem(tr("Download error: received HTTP error %1.").arg(getter->httpResponse()),LOGERROR); | ||
125 | m_logger->abort(); | ||
126 | return; | ||
127 | } | ||
128 | if(getter->isCached()) m_logger->addItem(tr("Cached file used."), LOGINFO); | ||
129 | if(error) { | ||
130 | m_logger->addItem(tr("Download error: %1").arg(getter->errorString()),LOGERROR); | ||
131 | m_logger->abort(); | ||
132 | return; | ||
133 | } | ||
134 | else m_logger->addItem(tr("Download finished."),LOGOK); | ||
135 | QApplication::processEvents(); | ||
136 | |||
137 | |||
138 | m_logger->setProgressMax(0); | ||
139 | //open downloaded file | ||
140 | QFile genlang(filename); | ||
141 | if(!genlang.open(QIODevice::ReadOnly)) | ||
142 | { | ||
143 | m_logger->addItem("failed to open downloaded file",LOGERROR); | ||
144 | m_logger->abort(); | ||
145 | return; | ||
146 | } | ||
147 | |||
148 | //tts | ||
149 | m_tts = getTTS(userSettings->value("tts").toString()); | ||
150 | m_tts->setUserCfg(userSettings); | ||
151 | |||
152 | if(!m_tts->start()) | ||
153 | { | ||
154 | m_logger->addItem("Init of TTS engine failed",LOGERROR); | ||
155 | m_logger->abort(); | ||
156 | return; | ||
157 | } | ||
158 | |||
159 | // Encoder | ||
160 | m_enc = getEncoder(userSettings->value("encoder").toString()); | ||
161 | m_enc->setUserCfg(userSettings); | ||
162 | |||
163 | if(!m_enc->start()) | ||
164 | { | ||
165 | m_logger->addItem("Init of Encoder engine failed",LOGERROR); | ||
166 | m_tts->stop(); | ||
167 | m_logger->abort(); | ||
168 | return; | ||
169 | } | ||
170 | |||
171 | QApplication::processEvents(); | ||
172 | |||
173 | connect(m_logger,SIGNAL(aborted()),this,SLOT(abort())); | ||
174 | QStringList mp3files; | ||
175 | |||
176 | QTextStream in(&genlang); | ||
177 | in.setCodec("UTF-8"); | ||
178 | |||
179 | bool emptyfile = true; | ||
180 | while (!in.atEnd()) | ||
181 | { | ||
182 | if(m_abort) | ||
183 | { | ||
184 | m_logger->addItem("aborted.",LOGERROR); | ||
185 | break; | ||
186 | } | ||
187 | |||
188 | QString comment = in.readLine(); | ||
189 | QString id = in.readLine(); | ||
190 | QString voice = in.readLine(); | ||
191 | |||
192 | id = id.remove("id:").remove('"').trimmed(); | ||
193 | voice = voice.remove("voice:").remove('"').trimmed(); | ||
194 | |||
195 | QString wavname = m_path + "/" + id + ".wav"; | ||
196 | QString toSpeak = voice; | ||
197 | QString encodedname = m_path + "/" + id +".mp3"; | ||
198 | |||
199 | // todo PAUSE | ||
200 | if(id == "VOICE_PAUSE") | ||
201 | { | ||
202 | QFile::copy(":/builtin/builtin/VOICE_PAUSE.wav",m_path + "/VOICE_PAUSE.wav"); | ||
203 | |||
204 | } | ||
205 | else | ||
206 | { | ||
207 | if(voice == "") continue; | ||
208 | |||
209 | m_logger->addItem(tr("creating ")+toSpeak,LOGINFO); | ||
210 | QApplication::processEvents(); | ||
211 | m_tts->voice(toSpeak,wavname); // generate wav | ||
212 | } | ||
213 | |||
214 | // todo strip | ||
215 | char buffer[255]; | ||
216 | |||
217 | wavtrim((char*)qPrintable(wavname),500,buffer,255); | ||
218 | |||
219 | // encode wav | ||
220 | m_enc->encode(wavname,encodedname); | ||
221 | // remove the wav file | ||
222 | QFile::remove(wavname); | ||
223 | // remember the mp3 file for later removing | ||
224 | mp3files << encodedname; | ||
225 | // remember that we have done something | ||
226 | emptyfile = false; | ||
227 | |||
228 | } | ||
229 | genlang.close(); | ||
230 | |||
231 | if(emptyfile) | ||
232 | { | ||
233 | m_logger->addItem(tr("The downloaded file was empty!"),LOGERROR); | ||
234 | m_logger->abort(); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | //make voicefile | ||
239 | FILE* ids2 = fopen(filename.toUtf8(), "r"); | ||
240 | if (ids2 == NULL) | ||
241 | { | ||
242 | m_logger->addItem("Error opening downloaded file",LOGERROR); | ||
243 | m_logger->abort(); | ||
244 | return; | ||
245 | } | ||
246 | |||
247 | FILE* output = fopen(QString(m_mountpoint + "/.rockbox/langs/" + m_lang + ".voice").toUtf8(), "wb"); | ||
248 | if (output == NULL) | ||
249 | { | ||
250 | m_logger->addItem("Error opening output file",LOGERROR); | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | voicefont(ids2,m_targetid,(char*)(const char*)m_path.toUtf8(), output); | ||
255 | |||
256 | //remove .mp3 files | ||
257 | for(int i=0;i< mp3files.size(); i++) | ||
258 | { | ||
259 | QFile::remove(mp3files.at(i)); | ||
260 | } | ||
261 | |||
262 | m_logger->setProgressMax(100); | ||
263 | m_logger->setProgressValue(100); | ||
264 | m_logger->addItem("successfully created.",LOGOK); | ||
265 | m_logger->abort(); | ||
266 | } | ||
267 | |||
268 | void VoiceFileCreator::updateDataReadProgress(int read, int total) | ||
269 | { | ||
270 | m_logger->setProgressMax(total); | ||
271 | m_logger->setProgressValue(read); | ||
272 | //qDebug() << "progress:" << read << "/" << total; | ||
273 | |||
274 | } | ||
275 | |||