summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDominik Wenger <domonoky@googlemail.com>2009-06-26 20:40:51 +0000
committerDominik Wenger <domonoky@googlemail.com>2009-06-26 20:40:51 +0000
commit20bf8aaf181dc5f24bad2628953c4d53782533cb (patch)
tree640787672cbe49dbbb23b8322d5a90595c2edf06
parent73d25744fb01844cc28402dfc4b48a030d270579 (diff)
downloadrockbox-20bf8aaf181dc5f24bad2628953c4d53782533cb.tar.gz
rockbox-20bf8aaf181dc5f24bad2628953c4d53782533cb.zip
rbutil: improve voice and talk generation.
- introduce a talkgenerator to better share code between voice and talk generation. - name intermediate .talkfiles after the md5sum of the text. (prevents naming problems). - do not directly use the logger, instead emit signals. - move talkfile and voicefile generation to base/ git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21524 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--rbutil/rbutilqt/base/talkfile.cpp263
-rw-r--r--rbutil/rbutilqt/base/talkfile.h (renamed from rbutil/rbutilqt/talkfile.h)33
-rw-r--r--rbutil/rbutilqt/base/talkgenerator.cpp238
-rw-r--r--rbutil/rbutilqt/base/talkgenerator.h78
-rw-r--r--rbutil/rbutilqt/base/voicefile.cpp246
-rw-r--r--rbutil/rbutilqt/base/voicefile.h (renamed from rbutil/rbutilqt/voicefile.h)30
-rw-r--r--rbutil/rbutilqt/createvoicewindow.cpp6
-rw-r--r--rbutil/rbutilqt/installtalkwindow.cpp7
-rw-r--r--rbutil/rbutilqt/rbutilqt.pro10
-rw-r--r--rbutil/rbutilqt/talkfile.cpp458
-rw-r--r--rbutil/rbutilqt/voicefile.cpp301
11 files changed, 871 insertions, 799 deletions
diff --git a/rbutil/rbutilqt/base/talkfile.cpp b/rbutil/rbutilqt/base/talkfile.cpp
new file mode 100644
index 0000000000..81dcf01ff5
--- /dev/null
+++ b/rbutil/rbutilqt/base/talkfile.cpp
@@ -0,0 +1,263 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2007 by Dominik Wenger
10 * $Id$
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 "talkfile.h"
21#include "rbsettings.h"
22
23TalkFileCreator::TalkFileCreator(QObject* parent): QObject(parent)
24{
25
26}
27
28//! \brief Creates Talkfiles.
29//!
30//! \param logger A pointer to a Loggerobject
31bool TalkFileCreator::createTalkFiles()
32{
33 m_abort = false;
34 QString errStr;
35
36 emit logItem(tr("Starting Talk file generation"),LOGINFO);
37 emit logProgress(0,0);
38 QCoreApplication::processEvents();
39
40 // read in Maps of paths - file/dirnames
41 emit logItem(tr("Reading Filelist..."),LOGINFO);
42 if(createTalkList(m_dir) == false)
43 {
44 emit logItem(tr("Talk file creation aborted"),LOGERROR);
45 doAbort();
46 return false;
47 }
48 QCoreApplication::processEvents();
49
50 // generate entries
51 {
52 TalkGenerator generator(this);
53 connect(&generator,SIGNAL(done(bool)),this,SIGNAL(done(bool)));
54 connect(&generator,SIGNAL(logItem(QString,int)),this,SIGNAL(logItem(QString,int)));
55 connect(&generator,SIGNAL(logProgress(int,int)),this,SIGNAL(logProgress(int,int)));
56 connect(this,SIGNAL(aborted()),&generator,SLOT(abort()));
57
58 if(generator.process(&m_talkList) == TalkGenerator::eERROR)
59 {
60 doAbort();
61 return false;
62 }
63 }
64
65 // Copying talk files
66 emit logItem(tr("Copying Talkfiles..."),LOGINFO);
67 if(copyTalkFiles(&errStr) == false)
68 {
69 emit logItem(errStr,LOGERROR);
70 doAbort();
71 return false;
72 }
73
74 // Deleting left overs
75 if( !cleanup())
76 return false;
77
78 emit logItem(tr("Finished creating Talk files"),LOGOK);
79 emit logProgress(1,1);
80 emit done(false);
81
82 return true;
83}
84
85//! \brief Strips everything after and including the last dot in a string. If there is no dot, nothing is changed
86//!
87//! \param filename The filename from which to strip the Extension
88//! \returns the modified string
89QString TalkFileCreator::stripExtension(QString filename)
90{
91 if(filename.lastIndexOf(".") != -1)
92 return filename.left(filename.lastIndexOf("."));
93 else
94 return filename;
95}
96
97//! \brief Does needed Tasks when we need to abort. Cleans up Files. Stops the Logger, Stops TTS and Encoder
98//!
99void TalkFileCreator::doAbort()
100{
101 cleanup();
102 emit logProgress(0,1);
103 emit done(true);
104}
105//! \brief creates a list of what to generate
106//!
107//! \param startDir The directory from which to start scanning
108bool TalkFileCreator::createTalkList(QDir startDir)
109{
110 m_talkList.clear();
111
112 // create Iterator
113 QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags;
114 if(m_recursive)
115 flags = QDirIterator::Subdirectories;
116
117 QDirIterator it(startDir,flags);
118
119 //create temp directory
120 QDir tempDir(QDir::tempPath()+ "/talkfiles/");
121 if(!tempDir.exists())
122 tempDir.mkpath(QDir::tempPath()+ "/talkfiles/");
123
124 // read in Maps of paths - file/dirnames
125 while (it.hasNext())
126 {
127 it.next();
128 if(m_abort)
129 {
130 return false;
131 }
132
133 QFileInfo fileInf = it.fileInfo();
134
135 // its a dir
136 if(fileInf.isDir())
137 {
138 QDir dir = fileInf.dir();
139
140 // insert into List
141 if(!dir.dirName().isEmpty() && m_talkFolders)
142 {
143 TalkGenerator::TalkEntry entry;
144 entry.toSpeak = dir.dirName();
145 entry.wavfilename = QDir::tempPath()+ "/talkfiles/" + QCryptographicHash::hash(entry.toSpeak.toUtf8(),
146 QCryptographicHash::Md5).toHex() + ".wav";
147 entry.talkfilename = QDir::tempPath()+ "/talkfiles/" + QCryptographicHash::hash(entry.toSpeak.toUtf8(),
148 QCryptographicHash::Md5).toHex() + ".talk";
149 entry.target = dir.path() + "/_dirname.talk";
150 entry.voiced = false;
151 entry.encoded = false;
152 qDebug() << "toSpeak: " << entry.toSpeak << " target: " << entry.target << " intermediates: " <<
153 entry.wavfilename << entry.talkfilename;
154 m_talkList.append(entry);
155 }
156 }
157 else // its a File
158 {
159 // insert into List
160 if( !fileInf.fileName().isEmpty() && !fileInf.fileName().endsWith(".talk") && m_talkFiles)
161 {
162 TalkGenerator::TalkEntry entry;
163 if(m_stripExtensions)
164 entry.toSpeak = stripExtension(fileInf.fileName());
165 else
166 entry.toSpeak = fileInf.fileName();
167 entry.wavfilename = QDir::tempPath()+ "/talkfiles/" + QCryptographicHash::hash(entry.toSpeak.toUtf8(),
168 QCryptographicHash::Md5).toHex() + ".wav";
169 entry.talkfilename = QDir::tempPath()+ "/talkfiles/" + QCryptographicHash::hash(entry.toSpeak.toUtf8(),
170 QCryptographicHash::Md5).toHex() + ".talk";
171 entry.target = fileInf.path() + "/" + fileInf.fileName() + ".talk";
172 entry.voiced = false;
173 entry.encoded = false;
174 qDebug() << "toSpeak: " << entry.toSpeak << " target: " << entry.target << " intermediates: " <<
175 entry.wavfilename << entry.talkfilename;
176 m_talkList.append(entry);
177 }
178 }
179 QCoreApplication::processEvents();
180 }
181 return true;
182}
183
184
185//! \brief copys Talkfiles from the temp dir to the target. Progress and installlog is handled inside
186//!
187//! \param errString Pointer to a QString where the error cause is written.
188//! \returns true on success, false on error or user abort
189bool TalkFileCreator::copyTalkFiles(QString* errString)
190{
191 int progressMax = m_talkList.size();
192 int m_progress = 0;
193 emit logProgress(m_progress,progressMax);
194
195 QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
196 installlog.beginGroup("talkfiles");
197
198 for(int i=0; i < m_talkList.size(); i++)
199 {
200 if(m_abort)
201 {
202 *errString = tr("File copy aborted");
203 return false;
204 }
205
206 // skip not encoded files
207 if(m_talkList[i].encoded == false)
208 {
209 emit logProgress(++m_progress,progressMax);
210 continue; // this file was skipped in one of the previous steps
211 }
212 // remove target if it exists, and if we should overwrite it
213 if(m_overwriteTalk && QFile::exists(m_talkList[i].target))
214 QFile::remove(m_talkList[i].target);
215
216 // copying
217 qDebug() << "copying " << m_talkList[i].talkfilename << "to" << m_talkList[i].target;
218 if(!QFile::copy(m_talkList[i].talkfilename,m_talkList[i].target))
219 {
220 *errString = tr("Copying of %1 to %2 failed").arg(m_talkList[i].talkfilename).arg(m_talkList[i].target);
221 return false;
222 }
223
224 // add to installlog
225 QString now = QDate::currentDate().toString("yyyyMMdd");
226 installlog.setValue(m_talkList[i].target.remove(0,m_mountpoint.length()),now);
227
228 emit logProgress(++m_progress,progressMax);
229 QCoreApplication::processEvents();
230 }
231 installlog.endGroup();
232 installlog.sync();
233 return true;
234}
235
236
237//! \brief Cleans up Files potentially left in the temp dir
238//!
239bool TalkFileCreator::cleanup()
240{
241 emit logItem(tr("Cleaning up.."),LOGINFO);
242
243 for(int i=0; i < m_talkList.size(); i++)
244 {
245 if(QFile::exists(m_talkList[i].wavfilename))
246 QFile::remove(m_talkList[i].wavfilename);
247 if(QFile::exists(m_talkList[i].talkfilename))
248 QFile::remove(m_talkList[i].talkfilename);
249
250 QCoreApplication::processEvents();
251 }
252 emit logItem(tr("Finished"),LOGINFO);
253 return true;
254}
255
256//! \brief slot, which is connected to the abort of the Logger. Sets a flag, so Creating Talkfiles ends at the next possible position
257//!
258void TalkFileCreator::abort()
259{
260 m_abort = true;
261 emit aborted();
262}
263
diff --git a/rbutil/rbutilqt/talkfile.h b/rbutil/rbutilqt/base/talkfile.h
index a6b9bb5490..f82421416a 100644
--- a/rbutil/rbutilqt/talkfile.h
+++ b/rbutil/rbutilqt/base/talkfile.h
@@ -26,8 +26,7 @@
26#include <QtCore> 26#include <QtCore>
27#include "progressloggerinterface.h" 27#include "progressloggerinterface.h"
28 28
29#include "encoders.h" 29#include "talkgenerator.h"
30#include "tts.h"
31 30
32class TalkFileCreator :public QObject 31class TalkFileCreator :public QObject
33{ 32{
@@ -36,7 +35,7 @@ class TalkFileCreator :public QObject
36public: 35public:
37 TalkFileCreator(QObject* parent); 36 TalkFileCreator(QObject* parent);
38 37
39 bool createTalkFiles(ProgressloggerInterface* logger); 38 bool createTalkFiles();
40 39
41 void setDir(QDir dir){m_dir = dir; } 40 void setDir(QDir dir){m_dir = dir; }
42 void setMountPoint(QString mountpoint) {m_mountpoint =mountpoint; } 41 void setMountPoint(QString mountpoint) {m_mountpoint =mountpoint; }
@@ -47,26 +46,26 @@ public:
47 void setTalkFolders(bool ov) {m_talkFolders = ov;} 46 void setTalkFolders(bool ov) {m_talkFolders = ov;}
48 void setTalkFiles(bool ov) {m_talkFiles = ov;} 47 void setTalkFiles(bool ov) {m_talkFiles = ov;}
49 48
50private slots: 49public slots:
51 void abort(); 50 void abort();
52 51
52signals:
53 void done(bool);
54 void aborted();
55 void logItem(QString, int); //! set logger item
56 void logProgress(int, int); //! set progress bar.
57
53private: 58private:
54 bool cleanup(QStringList list); 59 bool cleanup();
55 QString stripExtension(QString filename); 60 QString stripExtension(QString filename);
56 void doAbort(QStringList cleanupList); 61 void doAbort();
57 void resetProgress(int max); 62 void resetProgress(int max);
58 bool createDirAndFileMaps(QDir startDir,QMultiMap<QString,QString> *dirMap,QMultiMap<QString,QString> *fileMap); 63 bool copyTalkFiles(QString* errString);
59 TTSStatus voiceList(QStringList toSpeak,QStringList& voicedEntries);
60 bool encodeList(QStringList toEncode,QStringList& encodedEntries);
61 bool copyTalkDirFiles(QMultiMap<QString,QString> dirMap,QString* errString);
62 bool copyTalkFileFiles(QMultiMap<QString,QString> fileMap,QString* errString);
63 64
64 TTSBase* m_tts; 65 bool createTalkList(QDir startDir);
65 EncBase* m_enc;
66 66
67 QDir m_dir; 67 QDir m_dir;
68 QString m_mountpoint; 68 QString m_mountpoint;
69 int m_progress;
70 69
71 bool m_overwriteTalk; 70 bool m_overwriteTalk;
72 bool m_recursive; 71 bool m_recursive;
@@ -74,9 +73,9 @@ private:
74 bool m_talkFolders; 73 bool m_talkFolders;
75 bool m_talkFiles; 74 bool m_talkFiles;
76 75
77 ProgressloggerInterface* m_logger;
78
79 bool m_abort; 76 bool m_abort;
77
78 QList<TalkGenerator::TalkEntry> m_talkList;
80}; 79};
81 80
82 81
diff --git a/rbutil/rbutilqt/base/talkgenerator.cpp b/rbutil/rbutilqt/base/talkgenerator.cpp
new file mode 100644
index 0000000000..93a52a922e
--- /dev/null
+++ b/rbutil/rbutilqt/base/talkgenerator.cpp
@@ -0,0 +1,238 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2007 by Dominik Wenger
10 * $Id$
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 "talkgenerator.h"
21#include "rbsettings.h"
22#include "wavtrim.h"
23
24TalkGenerator::TalkGenerator(QObject* parent): QObject(parent)
25{
26
27}
28
29//! \brief Creates Talkfiles.
30//!
31TalkGenerator::Status TalkGenerator::process(QList<TalkEntry>* list,int wavtrimth)
32{
33 m_abort = false;
34 QString errStr;
35 bool warnings = false;
36
37 //tts
38 emit logItem(tr("Starting TTS Engine"),LOGINFO);
39 m_tts = TTSBase::getTTS(this,RbSettings::value(RbSettings::Tts).toString());
40 if(!m_tts->start(&errStr))
41 {
42 emit logItem(errStr.trimmed(),LOGERROR);
43 emit logItem(tr("Init of TTS engine failed"),LOGERROR);
44 emit done(true);
45 return eERROR;
46 }
47 QCoreApplication::processEvents();
48
49 // Encoder
50 emit logItem(tr("Starting Encoder Engine"),LOGINFO);
51 m_enc = EncBase::getEncoder(this,RbSettings::value(RbSettings::CurEncoder).toString());
52 if(!m_enc->start())
53 {
54 emit logItem(tr("Init of Encoder engine failed"),LOGERROR);
55 emit done(true);
56 m_tts->stop();
57 return eERROR;
58 }
59 QCoreApplication::processEvents();
60
61 emit logProgress(0,0);
62
63 // Voice entries
64 emit logItem(tr("Voicing entries..."),LOGINFO);
65 Status voiceStatus= voiceList(list,wavtrimth);
66 if(voiceStatus == eERROR)
67 {
68 m_tts->stop();
69 m_enc->stop();
70 emit done(true);
71 return eERROR;
72 }
73 else if( voiceStatus == eWARNING)
74 warnings = true;
75
76 QCoreApplication::processEvents();
77
78 // Encoding Entries
79 emit logItem(tr("Encoding files..."),LOGINFO);
80 Status encoderStatus = encodeList(list);
81 if( encoderStatus == eERROR)
82 {
83 m_tts->stop();
84 m_enc->stop();
85 emit done(true);
86 return eERROR;
87 }
88 else if( voiceStatus == eWARNING)
89 warnings = true;
90
91 QCoreApplication::processEvents();
92
93 m_tts->stop();
94 m_enc->stop();
95 emit logProgress(1,1);
96
97 if(warnings)
98 return eWARNING;
99 return eOK;
100}
101
102//! \brief Voices a List of string
103//!
104TalkGenerator::Status TalkGenerator::voiceList(QList<TalkEntry>* list,int wavtrimth)
105{
106 int progressMax = list->size();
107 int m_progress = 0;
108 emit logProgress(m_progress,progressMax);
109
110 QStringList errors;
111 QStringList dublicates;
112
113 bool warnings = false;
114 for(int i=0; i < list->size(); i++)
115 {
116 if(m_abort)
117 {
118 emit logItem(tr("Voicing aborted"), LOGERROR);
119 return eERROR;
120 }
121
122 // skip dublicated wav entrys
123 if(!dublicates.contains(list->at(i).wavfilename))
124 dublicates.append(list->at(i).wavfilename);
125 else
126 {
127 qDebug() << "dublicate skipped";
128 (*list)[i].voiced = true;
129 emit logProgress(++m_progress,progressMax);
130 continue;
131 }
132
133 // skip already voiced entrys
134 if(list->at(i).voiced == true)
135 {
136 emit logProgress(++m_progress,progressMax);
137 continue;
138 }
139 // skip entry whith empty text
140 if(list->at(i).toSpeak == "")
141 {
142 emit logProgress(++m_progress,progressMax);
143 continue;
144 }
145
146 // voice entry
147 QString error;
148 qDebug() << "voicing: " << list->at(i).toSpeak << "to" << list->at(i).wavfilename;
149 TTSStatus status = m_tts->voice(list->at(i).toSpeak,list->at(i).wavfilename, &error);
150 if(status == Warning)
151 {
152 warnings = true;
153 emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error),
154 LOGWARNING);
155 }
156 else if (status == FatalError)
157 {
158 emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error),
159 LOGERROR);
160 return eERROR;
161 }
162 else
163 (*list)[i].voiced = true;
164
165 //wavetrim if needed
166 if(wavtrimth != -1)
167 {
168 char buffer[255];
169 wavtrim(list->at(i).wavfilename.toLocal8Bit().data(),wavtrimth,buffer,255);
170 }
171
172 emit logProgress(++m_progress,progressMax);
173 QCoreApplication::processEvents();
174 }
175 if(warnings)
176 return eWARNING;
177 else
178 return eOK;
179}
180
181
182//! \brief Encodes a List of strings
183//!
184TalkGenerator::Status TalkGenerator::encodeList(QList<TalkEntry>* list)
185{
186 QStringList dublicates;
187
188 int progressMax = list->size();
189 int m_progress = 0;
190 emit logProgress(m_progress,progressMax);
191
192 for(int i=0; i < list->size(); i++)
193 {
194 if(m_abort)
195 {
196 emit logItem(tr("Encoding aborted"), LOGERROR);
197 return eERROR;
198 }
199
200 //skip non-voiced entrys
201 if(list->at(i).voiced == false)
202 {
203 qDebug() << "non voiced entry" << list->at(i).toSpeak <<"detected";
204 emit logProgress(++m_progress,progressMax);
205 continue;
206 }
207 //skip dublicates
208 if(!dublicates.contains(list->at(i).talkfilename))
209 dublicates.append(list->at(i).talkfilename);
210 else
211 {
212 qDebug() << "dublicate skipped";
213 (*list)[i].encoded = true;
214 emit logProgress(++m_progress,progressMax);
215 continue;
216 }
217
218 //encode entry
219 qDebug() << "encoding " << list->at(i).wavfilename << "to" << list->at(i).talkfilename;
220 if(!m_enc->encode(list->at(i).wavfilename,list->at(i).talkfilename))
221 {
222 emit logItem(tr("Encoding of %1 failed").arg(list->at(i).wavfilename), LOGERROR);
223 return eERROR;
224 }
225 (*list)[i].encoded = true;
226 emit logProgress(++m_progress,progressMax);
227 QCoreApplication::processEvents();
228 }
229 return eOK;
230}
231
232//! \brief slot, which is connected to the abort of the Logger. Sets a flag, so Creating Talkfiles ends at the next possible position
233//!
234void TalkGenerator::abort()
235{
236 m_abort = true;
237}
238
diff --git a/rbutil/rbutilqt/base/talkgenerator.h b/rbutil/rbutilqt/base/talkgenerator.h
new file mode 100644
index 0000000000..eb08df8d51
--- /dev/null
+++ b/rbutil/rbutilqt/base/talkgenerator.h
@@ -0,0 +1,78 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2007 by Dominik Wenger
10 * $Id$
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22
23#ifndef TALKGENERATOR_H
24#define TALKGENERATOR_H
25
26#include <QtCore>
27#include "progressloggerinterface.h"
28
29#include "encoders.h"
30#include "tts.h"
31
32//! \brief Talk generator, generates .wav and .talk files out of a list.
33class TalkGenerator :public QObject
34{
35 Q_OBJECT
36public:
37 enum Status
38 {
39 eOK,
40 eWARNING,
41 eERROR
42 };
43
44 struct TalkEntry
45 {
46 QString toSpeak;
47 QString wavfilename;
48 QString talkfilename;
49 QString target;
50 bool voiced;
51 bool encoded;
52 };
53
54 TalkGenerator(QObject* parent);
55
56 Status process(QList<TalkEntry>* list,int wavtrimth = -1);
57
58public slots:
59 void abort();
60
61signals:
62 void done(bool);
63 void logItem(QString, int); //! set logger item
64 void logProgress(int, int); //! set progress bar.
65
66private:
67 Status voiceList(QList<TalkEntry>* list,int wavetrimth);
68 Status encodeList(QList<TalkEntry>* list);
69
70 TTSBase* m_tts;
71 EncBase* m_enc;
72
73 bool m_abort;
74};
75
76
77#endif
78
diff --git a/rbutil/rbutilqt/base/voicefile.cpp b/rbutil/rbutilqt/base/voicefile.cpp
new file mode 100644
index 0000000000..3b80c1ff12
--- /dev/null
+++ b/rbutil/rbutilqt/base/voicefile.cpp
@@ -0,0 +1,246 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2007 by Dominik Wenger
10 * $Id$
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#include "utils.h"
22#include "rbsettings.h"
23
24VoiceFileCreator::VoiceFileCreator(QObject* parent) :QObject(parent)
25{
26 m_wavtrimThreshold=500;
27}
28
29void VoiceFileCreator::abort()
30{
31 m_abort = true;
32 emit aborted();
33}
34
35bool VoiceFileCreator::createVoiceFile()
36{
37 m_talkList.clear();
38 m_abort = false;
39 emit logItem(tr("Starting Voicefile generation"),LOGINFO);
40
41 // test if tempdir exists
42 if(!QDir(QDir::tempPath()+"/rbvoice/").exists())
43 {
44 QDir(QDir::tempPath()).mkdir("rbvoice");
45 }
46 m_path = QDir::tempPath() + "/rbvoice/";
47
48 // read rockbox-info.txt
49 RockboxInfo info(m_mountpoint);
50 if(!info.open())
51 {
52 emit logItem(tr("could not find rockbox-info.txt"),LOGERROR);
53 emit done(true);
54 return false;
55 }
56
57 QString target = info.target();
58 QString features = info.features();
59 QString version = info.version();
60 version = version.left(version.indexOf("-")).remove(0,1);
61
62 //prepare download url
63 QUrl genlangUrl = RbSettings::value(RbSettings::GenlangUrl).toString()
64 +"?lang=" + m_lang + "&t=" + target + "&rev=" + version + "&f=" + features;
65
66 qDebug() << "downloading " << genlangUrl;
67
68 //download the correct genlang output
69 QTemporaryFile *downloadFile = new QTemporaryFile(this);
70 downloadFile->open();
71 filename = downloadFile->fileName();
72 downloadFile->close();
73 // get the real file.
74 getter = new HttpGet(this);
75 getter->setFile(downloadFile);
76
77 connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
78 connect(getter, SIGNAL(dataReadProgress(int, int)), this, SIGNAL(logProgress(int, int)));
79 connect(this, SIGNAL(aborted()), getter, SLOT(abort()));
80 emit logItem(tr("Downloading voice info.."),LOGINFO);
81 getter->getFile(genlangUrl);
82 return true;
83 }
84
85
86void VoiceFileCreator::downloadDone(bool error)
87{
88 qDebug() << "Voice creator::downloadDone, error:" << error;
89
90 // update progress bar
91 emit logProgress(1,1);
92 if(getter->httpResponse() != 200 && !getter->isCached()) {
93 emit logItem(tr("Download error: received HTTP error %1.").arg(getter->httpResponse()),LOGERROR);
94 emit done(true);
95 return;
96 }
97
98 if(getter->isCached())
99 emit logItem(tr("Cached file used."), LOGINFO);
100 if(error)
101 {
102 emit logItem(tr("Download error: %1").arg(getter->errorString()),LOGERROR);
103 emit done(true);
104 return;
105 }
106 else
107 emit logItem(tr("Download finished."),LOGINFO);
108
109 QCoreApplication::processEvents();
110
111 //open downloaded file
112 QFile genlang(filename);
113 if(!genlang.open(QIODevice::ReadOnly))
114 {
115 emit logItem(tr("failed to open downloaded file"),LOGERROR);
116 emit done(true);
117 return;
118 }
119
120 QCoreApplication::processEvents();
121
122 //read in downloaded file
123 emit logItem(tr("Reading strings..."),LOGINFO);
124 QTextStream in(&genlang);
125 in.setCodec("UTF-8");
126 QString id, voice;
127 bool idfound = false;
128 bool voicefound=false;
129 while (!in.atEnd())
130 {
131 QString line = in.readLine();
132 if(line.contains("id:")) //ID found
133 {
134 id = line.remove("id:").remove('"').trimmed();
135 idfound = true;
136 }
137 else if(line.contains("voice:")) // voice found
138 {
139 voice = line.remove("voice:").remove('"').trimmed();
140 voicefound=true;
141 }
142
143 if(idfound && voicefound)
144 {
145 TalkGenerator::TalkEntry entry;
146 entry.toSpeak = voice;
147 entry.wavfilename = m_path + "/" + id + ".wav";
148 entry.talkfilename = m_path + "/" + id + ".mp3"; //voicefont wants them with .mp3 extension
149 entry.voiced = false;
150 entry.encoded = false;
151 if(id == "VOICE_PAUSE")
152 {
153 QFile::copy(":/builtin/VOICE_PAUSE.wav",m_path + "/VOICE_PAUSE.wav");
154 entry.wavfilename = m_path + "/VOICE_PAUSE.wav";
155 entry.voiced = true;
156 }
157 m_talkList.append(entry);
158 idfound=false;
159 voicefound=false;
160 }
161 }
162 genlang.close();
163
164 // check for empty list
165 if(m_talkList.size() == 0)
166 {
167 emit logItem(tr("The downloaded file was empty!"),LOGERROR);
168 emit done(true);
169 return;
170 }
171
172 // generate files
173 {
174 TalkGenerator generator(this);
175 connect(&generator,SIGNAL(done(bool)),this,SIGNAL(done(bool)));
176 connect(&generator,SIGNAL(logItem(QString,int)),this,SIGNAL(logItem(QString,int)));
177 connect(&generator,SIGNAL(logProgress(int,int)),this,SIGNAL(logProgress(int,int)));
178 connect(this,SIGNAL(aborted()),&generator,SLOT(abort()));
179
180 if(generator.process(&m_talkList) == TalkGenerator::eERROR)
181 {
182 cleanup();
183 emit logProgress(0,1);
184 emit done(true);
185 return;
186 }
187 }
188
189 //make voicefile
190 emit logItem(tr("Creating voicefiles..."),LOGINFO);
191 FILE* ids2 = fopen(filename.toLocal8Bit(), "r");
192 if (ids2 == NULL)
193 {
194 cleanup();
195 emit logItem(tr("Error opening downloaded file"),LOGERROR);
196 emit done(true);
197 return;
198 }
199
200 FILE* output = fopen(QString(m_mountpoint + "/.rockbox/langs/" + m_lang + ".voice").toLocal8Bit(), "wb");
201 if (output == NULL)
202 {
203 cleanup();
204 emit logItem(tr("Error opening output file"),LOGERROR);
205 emit done(true);
206 return;
207 }
208
209 voicefont(ids2,m_targetid,m_path.toLocal8Bit().data(), output);
210
211 //cleanup
212 cleanup();
213
214 // Add Voice file to the install log
215 QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
216 installlog.beginGroup("selfcreated Voice");
217 installlog.setValue("/.rockbox/langs/" + m_lang + ".voice",QDate::currentDate().toString("yyyyMMdd"));
218 installlog.endGroup();
219 installlog.sync();
220
221 emit logProgress(1,1);
222 emit logItem(tr("successfully created."),LOGOK);
223
224 emit done(false);
225}
226
227//! \brief Cleans up Files potentially left in the temp dir
228//!
229void VoiceFileCreator::cleanup()
230{
231 emit logItem(tr("Cleaning up.."),LOGINFO);
232
233 for(int i=0; i < m_talkList.size(); i++)
234 {
235 if(QFile::exists(m_talkList[i].wavfilename))
236 QFile::remove(m_talkList[i].wavfilename);
237 if(QFile::exists(m_talkList[i].talkfilename))
238 QFile::remove(m_talkList[i].talkfilename);
239
240 QCoreApplication::processEvents();
241 }
242 emit logItem(tr("Finished"),LOGINFO);
243
244 return;
245}
246
diff --git a/rbutil/rbutilqt/voicefile.h b/rbutil/rbutilqt/base/voicefile.h
index 0bc4df8312..26c4a408f7 100644
--- a/rbutil/rbutilqt/voicefile.h
+++ b/rbutil/rbutilqt/base/voicefile.h
@@ -26,12 +26,9 @@
26#include <QtCore> 26#include <QtCore>
27#include "progressloggerinterface.h" 27#include "progressloggerinterface.h"
28 28
29#include "encoders.h"
30#include "tts.h"
31#include "httpget.h" 29#include "httpget.h"
32
33#include "wavtrim.h"
34#include "voicefont.h" 30#include "voicefont.h"
31#include "talkgenerator.h"
35 32
36class VoiceFileCreator :public QObject 33class VoiceFileCreator :public QObject
37{ 34{
@@ -40,39 +37,38 @@ public:
40 VoiceFileCreator(QObject* parent); 37 VoiceFileCreator(QObject* parent);
41 38
42 //start creation 39 //start creation
43 bool createVoiceFile(ProgressloggerInterface* logger); 40 bool createVoiceFile();
44 41
45 void setMountPoint(QString mountpoint) {m_mountpoint =mountpoint; } 42 void setMountPoint(QString mountpoint) {m_mountpoint =mountpoint; }
46 void setTargetId(int id){m_targetid = id;} 43 void setTargetId(int id){m_targetid = id;}
47 void setLang(QString name){m_lang =name;} 44 void setLang(QString name){m_lang =name;}
48 void setWavtrimThreshold(int th){m_wavtrimThreshold = th;} 45 void setWavtrimThreshold(int th){m_wavtrimThreshold = th;}
49 46
47public slots:
48 void abort();
49
50signals: 50signals:
51 void done(bool error); 51 void done(bool);
52 void aborted();
53 void logItem(QString, int); //! set logger item
54 void logProgress(int, int); //! set progress bar.
52 55
53private slots: 56private slots:
54 void abort();
55 void downloadDone(bool error); 57 void downloadDone(bool error);
56 void updateDataReadProgress(int read, int total);
57 58
58private: 59private:
59 60 void cleanup();
60 // ptr to encoder, tts and settings 61
61 TTSBase* m_tts;
62 EncBase* m_enc;
63 HttpGet *getter; 62 HttpGet *getter;
64
65 QString filename; //the temporary file 63 QString filename; //the temporary file
66
67 QString m_mountpoint; //mountpoint of the device 64 QString m_mountpoint; //mountpoint of the device
68 QString m_path; //path where the wav and mp3 files are stored to 65 QString m_path; //path where the wav and mp3 files are stored to
69 int m_targetid; //the target id 66 int m_targetid; //the target id
70 QString m_lang; // the language which will be spoken 67 QString m_lang; // the language which will be spoken
71 int m_wavtrimThreshold; 68 int m_wavtrimThreshold;
72 69
73 ProgressloggerInterface* m_logger;
74
75 bool m_abort; 70 bool m_abort;
71 QList<TalkGenerator::TalkEntry> m_talkList;
76}; 72};
77 73
78#endif 74#endif
diff --git a/rbutil/rbutilqt/createvoicewindow.cpp b/rbutil/rbutilqt/createvoicewindow.cpp
index 01c9a256b7..268e9f50e7 100644
--- a/rbutil/rbutilqt/createvoicewindow.cpp
+++ b/rbutil/rbutilqt/createvoicewindow.cpp
@@ -60,7 +60,11 @@ void CreateVoiceWindow::accept()
60 voicecreator->setWavtrimThreshold(wvThreshold); 60 voicecreator->setWavtrimThreshold(wvThreshold);
61 61
62 //start creating 62 //start creating
63 voicecreator->createVoiceFile(logger); 63 connect(voicecreator, SIGNAL(done(bool)), logger, SLOT(setFinished()));
64 connect(voicecreator, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
65 connect(voicecreator, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
66 connect(logger,SIGNAL(aborted()),voicecreator,SLOT(abort()));
67 voicecreator->createVoiceFile();
64} 68}
65 69
66 70
diff --git a/rbutil/rbutilqt/installtalkwindow.cpp b/rbutil/rbutilqt/installtalkwindow.cpp
index 6277313d3a..f225632f22 100644
--- a/rbutil/rbutilqt/installtalkwindow.cpp
+++ b/rbutil/rbutilqt/installtalkwindow.cpp
@@ -103,7 +103,12 @@ void InstallTalkWindow::accept()
103 talkcreator->setTalkFolders(ui.talkFolders->isChecked()); 103 talkcreator->setTalkFolders(ui.talkFolders->isChecked());
104 talkcreator->setTalkFiles(ui.talkFiles->isChecked()); 104 talkcreator->setTalkFiles(ui.talkFiles->isChecked());
105 105
106 talkcreator->createTalkFiles(logger); 106 connect(talkcreator, SIGNAL(done(bool)), logger, SLOT(setFinished()));
107 connect(talkcreator, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
108 connect(talkcreator, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
109 connect(logger,SIGNAL(aborted()),talkcreator,SLOT(abort()));
110
111 talkcreator->createTalkFiles();
107} 112}
108 113
109 114
diff --git a/rbutil/rbutilqt/rbutilqt.pro b/rbutil/rbutilqt/rbutilqt.pro
index 3edcbdc11b..3223b91828 100644
--- a/rbutil/rbutilqt/rbutilqt.pro
+++ b/rbutil/rbutilqt/rbutilqt.pro
@@ -53,7 +53,8 @@ SOURCES += rbutilqt.cpp \
53 base/zipinstaller.cpp \ 53 base/zipinstaller.cpp \
54 progressloggergui.cpp \ 54 progressloggergui.cpp \
55 installtalkwindow.cpp \ 55 installtalkwindow.cpp \
56 talkfile.cpp \ 56 base/talkfile.cpp \
57 base/talkgenerator.cpp \
57 base/autodetection.cpp \ 58 base/autodetection.cpp \
58 ../ipodpatcher/ipodpatcher.c \ 59 ../ipodpatcher/ipodpatcher.c \
59 ../sansapatcher/sansapatcher.c \ 60 ../sansapatcher/sansapatcher.c \
@@ -69,7 +70,7 @@ SOURCES += rbutilqt.cpp \
69 base/tts.cpp \ 70 base/tts.cpp \
70 ../../tools/wavtrim.c \ 71 ../../tools/wavtrim.c \
71 ../../tools/voicefont.c \ 72 ../../tools/voicefont.c \
72 voicefile.cpp \ 73 base/voicefile.cpp \
73 createvoicewindow.cpp \ 74 createvoicewindow.cpp \
74 base/rbsettings.cpp \ 75 base/rbsettings.cpp \
75 base/rbunzip.cpp \ 76 base/rbunzip.cpp \
@@ -97,7 +98,8 @@ HEADERS += rbutilqt.h \
97 version.h \ 98 version.h \
98 base/zipinstaller.h \ 99 base/zipinstaller.h \
99 installtalkwindow.h \ 100 installtalkwindow.h \
100 talkfile.h \ 101 base/talkfile.h \
102 base/talkgenerator.h \
101 base/autodetection.h \ 103 base/autodetection.h \
102 progressloggerinterface.h \ 104 progressloggerinterface.h \
103 progressloggergui.h \ 105 progressloggergui.h \
@@ -121,7 +123,7 @@ HEADERS += rbutilqt.h \
121 base/tts.h \ 123 base/tts.h \
122 ../../tools/wavtrim.h \ 124 ../../tools/wavtrim.h \
123 ../../tools/voicefont.h \ 125 ../../tools/voicefont.h \
124 voicefile.h \ 126 base/voicefile.h \
125 createvoicewindow.h \ 127 createvoicewindow.h \
126 base/rbsettings.h \ 128 base/rbsettings.h \
127 base/rbunzip.h \ 129 base/rbunzip.h \
diff --git a/rbutil/rbutilqt/talkfile.cpp b/rbutil/rbutilqt/talkfile.cpp
deleted file mode 100644
index 815c2824fb..0000000000
--- a/rbutil/rbutilqt/talkfile.cpp
+++ /dev/null
@@ -1,458 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2007 by Dominik Wenger
10 * $Id$
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 "talkfile.h"
21#include "rbsettings.h"
22
23TalkFileCreator::TalkFileCreator(QObject* parent): QObject(parent)
24{
25
26}
27
28//! \brief Creates Talkfiles.
29//!
30//! \param logger A pointer to a Loggerobject
31bool TalkFileCreator::createTalkFiles(ProgressloggerInterface* logger)
32{
33 m_abort = false;
34 m_logger = logger;
35
36 QMultiMap<QString,QString> fileList;
37 QMultiMap<QString,QString> dirList;
38 QStringList toSpeakList, voicedEntries, encodedEntries;
39 QString errStr;
40
41 m_logger->addItem(tr("Starting Talk file generation"),LOGINFO);
42
43 //tts
44 m_tts = TTSBase::getTTS(this,RbSettings::value(RbSettings::Tts).toString());
45
46 if(!m_tts->start(&errStr))
47 {
48 m_logger->addItem(errStr.trimmed(),LOGERROR);
49 m_logger->addItem(tr("Init of TTS engine failed"),LOGERROR);
50 m_logger->setFinished();
51 return false;
52 }
53
54 // Encoder
55 m_enc = EncBase::getEncoder(this,RbSettings::value(RbSettings::CurEncoder).toString());
56
57 if(!m_enc->start())
58 {
59 m_logger->addItem(tr("Init of Encoder engine failed"),LOGERROR);
60 m_logger->setFinished();
61 m_tts->stop();
62 return false;
63 }
64
65 QCoreApplication::processEvents();
66
67 connect(logger,SIGNAL(aborted()),this,SLOT(abort()));
68 m_logger->setProgressMax(0);
69
70 // read in Maps of paths - file/dirnames
71 m_logger->addItem(tr("Reading Filelist..."),LOGINFO);
72 if(createDirAndFileMaps(m_dir,&dirList,&fileList) == false)
73 {
74 m_logger->addItem(tr("Talk file creation aborted"),LOGERROR);
75 doAbort(toSpeakList);
76 return false;
77 }
78
79 // create List of all Files/Dirs to speak
80 QMapIterator<QString, QString> dirIt(dirList);
81 while (dirIt.hasNext())
82 {
83 dirIt.next();
84 // insert only non dublicate dir entries into list
85 if(!toSpeakList.contains(dirIt.value()))
86 {
87 qDebug() << "toSpeaklist dir:" << dirIt.value();
88 toSpeakList.append(dirIt.value());
89 }
90 }
91 QMapIterator<QString, QString> fileIt(fileList);
92 while (fileIt.hasNext())
93 {
94 fileIt.next();
95 // insert only non- dublictae file entries into list
96 if(!toSpeakList.contains(fileIt.value()))
97 {
98 if(m_stripExtensions)
99 toSpeakList.append(stripExtension(fileIt.value()));
100 else
101 toSpeakList.append(fileIt.value());
102 }
103 }
104
105 // Voice entries
106 m_logger->addItem(tr("Voicing entries..."),LOGINFO);
107 TTSStatus voiceStatus= voiceList(toSpeakList,voicedEntries);
108 if(voiceStatus == FatalError)
109 {
110 doAbort(toSpeakList);
111 return false;
112 }
113
114 // Encoding Entries
115 m_logger->addItem(tr("Encoding files..."),LOGINFO);
116 if(encodeList(voicedEntries,encodedEntries) == false)
117 {
118 doAbort(toSpeakList);
119 return false;
120 }
121
122 // Copying talk files
123 m_logger->addItem(tr("Copying Talkfile for Dirs..."),LOGINFO);
124 if(copyTalkDirFiles(dirList,&errStr) == false)
125 {
126 m_logger->addItem(errStr,LOGERROR);
127 doAbort(toSpeakList);
128 return false;
129 }
130
131 //Copying file talk files
132 m_logger->addItem(tr("Copying Talkfile for Files..."),LOGINFO);
133 if(copyTalkFileFiles(fileList,&errStr) == false)
134 {
135 m_logger->addItem(errStr,LOGERROR);
136 doAbort(toSpeakList);
137 return false;
138 }
139
140 // Deleting left overs
141 if( !cleanup(toSpeakList))
142 return false;
143
144 m_tts->stop();
145 m_enc->stop();
146 m_logger->addItem(tr("Finished creating Talk files"),LOGOK);
147 m_logger->setProgressMax(1);
148 m_logger->setProgressValue(1);
149 m_logger->setFinished();
150
151 return true;
152}
153
154//! \brief resets the internal progress counter, and sets the Progressbar in the Logger
155//!
156//! \param max The maximum to shich the Progressbar is set.
157void TalkFileCreator::resetProgress(int max)
158{
159 m_progress = 0;
160 m_logger->setProgressMax(max);
161 m_logger->setProgressValue(m_progress);
162}
163
164//! \brief Strips everything after and including the last dot in a string. If there is no dot, nothing is changed
165//!
166//! \param filename The filename from which to strip the Extension
167//! \returns the modified string
168QString TalkFileCreator::stripExtension(QString filename)
169{
170 if(filename.lastIndexOf(".") != -1)
171 return filename.left(filename.lastIndexOf("."));
172 else
173 return filename;
174}
175
176//! \brief Does needed Tasks when we need to abort. Cleans up Files. Stops the Logger, Stops TTS and Encoder
177//!
178//! \param cleanupList List of filenames to give to cleanup()
179void TalkFileCreator::doAbort(QStringList cleanupList)
180{
181 cleanup(cleanupList);
182 m_logger->setProgressMax(1);
183 m_logger->setProgressValue(0);
184 m_logger->setFinished();
185 m_tts->stop();
186 m_enc->stop();
187}
188
189//! \brief Creates MultiMaps (paths -> File/dir names) of all Dirs and Files in a Folder.
190//! Depending on settings, either Dirs or Files can be ignored.
191//! Also recursion is controlled by settings
192//!
193//! \param startDir The dir where it beginns scanning
194//! \param dirMap The MulitMap where the dirs are stored
195//! \param filMap The MultiMap where Files are stored
196//! \returns true on Success, false if User aborted.
197bool TalkFileCreator::createDirAndFileMaps(QDir startDir,QMultiMap<QString,QString> *dirMap,QMultiMap<QString,QString> *fileMap)
198{
199 // create Iterator
200 QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags;
201 if(m_recursive)
202 flags = QDirIterator::Subdirectories;
203
204 QDirIterator it(startDir,flags);
205
206 // read in Maps of paths - file/dirnames
207 while (it.hasNext())
208 {
209 it.next();
210 if(m_abort)
211 {
212 return false;
213 }
214
215 QFileInfo fileInf = it.fileInfo();
216
217 // its a dir
218 if(fileInf.isDir())
219 {
220 QDir dir = fileInf.dir();
221
222 // insert into List
223 if(!dir.dirName().isEmpty() && m_talkFolders)
224 {
225 qDebug() << "Dir: " << dir.dirName() << " - " << dir.path();
226 dirMap->insert(dir.path(),dir.dirName());
227 }
228 }
229 else // its a File
230 {
231 // insert into List
232 if( !fileInf.fileName().isEmpty() && !fileInf.fileName().endsWith(".talk") && m_talkFiles)
233 {
234 qDebug() << "File: " << fileInf.fileName() << " - " << fileInf.path();
235 fileMap->insert(fileInf.path(),fileInf.fileName());
236 }
237 }
238 QCoreApplication::processEvents();
239 }
240 return true;
241}
242
243//! \brief Voices a List of string to the temp dir. Progress is handled inside.
244//!
245//! \param toSpeak QStringList with the Entries to voice.
246//! \param errString pointer to where the Error cause is written
247//! \returns true on success, false on error or user abort
248TTSStatus TalkFileCreator::voiceList(QStringList toSpeak,QStringList& voicedEntries)
249{
250 resetProgress(toSpeak.size());
251 QStringList errors;
252
253 bool warnings = false;
254 for(int i=0; i < toSpeak.size(); i++)
255 {
256 if(m_abort)
257 {
258 m_logger->addItem(tr("Talk file creation aborted"), LOGERROR);
259 return FatalError;
260 }
261
262 QString filename = QDir::tempPath()+ "/"+ toSpeak[i] + ".wav";
263
264 QString error;
265 TTSStatus status = m_tts->voice(toSpeak[i],filename, &error);
266 if(status == Warning)
267 {
268 warnings = true;
269 m_logger->addItem(tr("Voicing of %1 failed: %2").arg(toSpeak[i]).arg(error),
270 LOGWARNING);
271 }
272 else if (status == FatalError)
273 {
274 m_logger->addItem(tr("Voicing of %1 failed: %2").arg(toSpeak[i]).arg(error),
275 LOGERROR);
276 return FatalError;
277 }
278 else
279 voicedEntries.append(toSpeak[i]);
280 m_logger->setProgressValue(++m_progress);
281 QCoreApplication::processEvents();
282 }
283 if(warnings)
284 return Warning;
285 else
286 return NoError;
287}
288
289
290//! \brief Encodes a List of strings from/to the temp dir. Progress is handled inside.
291//! It expects the inputfile in the temp dir with the name in the List appended with ".wav"
292//!
293//! \param toSpeak QStringList with the Entries to encode.
294//! \param errString pointer to where the Error cause is written
295//! \returns true on success, false on error or user abort
296bool TalkFileCreator::encodeList(QStringList toEncode,QStringList& encodedEntries)
297{
298 resetProgress(toEncode.size());
299 for(int i=0; i < toEncode.size(); i++)
300 {
301 if(m_abort)
302 {
303 m_logger->addItem(tr("Talk file creation aborted"), LOGERROR);
304 return false;
305 }
306
307 QString wavfilename = QDir::tempPath()+ "/"+ toEncode[i] + ".wav";
308 QString filename = QDir::tempPath()+ "/"+ toEncode[i] + ".talk";
309
310 if(!m_enc->encode(wavfilename,filename))
311 {
312 m_logger->addItem(tr("Encoding of %1 failed").arg(filename), LOGERROR);
313 return false;
314 }
315 encodedEntries.append(toEncode[i]);
316 m_logger->setProgressValue(++m_progress);
317 QCoreApplication::processEvents();
318 }
319 return true;
320}
321
322//! \brief copys Talkfile for Dirs from the temp dir to the target. Progress and installlog is handled inside
323//!
324//! \param dirMap a MultiMap of Paths -> Dirnames
325//! \param errString Pointer to a QString where the error cause is written.
326//! \returns true on success, false on error or user abort
327bool TalkFileCreator::copyTalkDirFiles(QMultiMap<QString,QString> dirMap,QString* errString)
328{
329 resetProgress(dirMap.size());
330
331 QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
332 installlog.beginGroup("talkfiles");
333
334 QMapIterator<QString, QString> it(dirMap);
335 while (it.hasNext())
336 {
337 it.next();
338 if(m_abort)
339 {
340 *errString = tr("Talk file creation aborted");
341 return false;
342 }
343
344 QString source = QDir::tempPath()+ "/"+ it.value() + ".talk";
345
346 if(!QFileInfo(source).exists())
347 continue; // this file was skipped in one of the previous steps
348
349 QString target = it.key() + "/" + "_dirname.talk";
350
351 // remove target if it exists, and if we should overwrite it
352 if(m_overwriteTalk && QFile::exists(target))
353 QFile::remove(target);
354
355 // copying
356 if(!QFile::copy(source,target))
357 {
358 *errString = tr("Copying of %1 to %2 failed").arg(source).arg(target);
359 return false;
360 }
361
362 // add to installlog
363 QString now = QDate::currentDate().toString("yyyyMMdd");
364 installlog.setValue(target.remove(0,m_mountpoint.length()),now);
365
366 m_logger->setProgressValue(++m_progress);
367 QCoreApplication::processEvents();
368 }
369 installlog.endGroup();
370 installlog.sync();
371 return true;
372}
373
374//! \brief copys Talkfile for Files from the temp dir to the target. Progress and installlog is handled inside
375//!
376//! \param fileMap a MultiMap of Paths -> Filenames
377//! \param errString Pointer to a QString where the error cause is written.
378//! \returns true on success, false on error or user abort
379bool TalkFileCreator::copyTalkFileFiles(QMultiMap<QString,QString> fileMap,QString* errString)
380{
381 resetProgress(fileMap.size());
382
383 QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
384 installlog.beginGroup("talkfiles");
385
386 QMapIterator<QString, QString> it(fileMap);
387 while (it.hasNext())
388 {
389 it.next();
390 if(m_abort)
391 {
392 *errString = tr("Talk file creation aborted");
393 return false;
394 }
395
396 QString source;
397 QString target = it.key() + "/" + it.value() + ".talk";
398
399 // correct source if we hav stripExtension enabled
400 if(m_stripExtensions)
401 source = QDir::tempPath()+ "/"+ stripExtension(it.value()) + ".talk";
402 else
403 source = QDir::tempPath()+ "/"+ it.value() + ".talk";
404
405 if(!QFileInfo(source).exists())
406 continue; // this file was skipped in one of the previous steps
407
408 // remove target if it exists, and if we should overwrite it
409 if(m_overwriteTalk && QFile::exists(target))
410 QFile::remove(target);
411
412 // copy file
413 qDebug() << "copying: " << source << " to " << target;
414 if(!QFile::copy(source,target))
415 {
416 *errString = tr("Copying of %1 to %2 failed").arg(source).arg(target);
417 return false;
418 }
419
420 // add to Install log
421 QString now = QDate::currentDate().toString("yyyyMMdd");
422 installlog.setValue(target.remove(0,m_mountpoint.length()),now);
423
424 m_logger->setProgressValue(++m_progress);
425 QCoreApplication::processEvents();
426 }
427 installlog.endGroup();
428 installlog.sync();
429 return true;
430}
431
432
433//! \brief Cleans up Files potentially left in the temp dir
434//!
435//! \param list List of file to try to delete in the temp dir. Function appends ".wav" and ".talk" to the filenames
436bool TalkFileCreator::cleanup(QStringList list)
437{
438 m_logger->addItem(tr("Cleaning up.."),LOGINFO);
439
440 for(int i=0; i < list.size(); i++)
441 {
442 if(QFile::exists(QDir::tempPath()+ "/"+ list[i] + ".wav"))
443 QFile::remove(QDir::tempPath()+ "/"+ list[i] + ".wav");
444 if(QFile::exists(QDir::tempPath()+ "/"+ list[i] + ".talk"))
445 QFile::remove(QDir::tempPath()+ "/"+ list[i] + ".talk");
446
447 QCoreApplication::processEvents();
448 }
449 return true;
450}
451
452//! \brief slot, which is connected to the abort of the Logger. Sets a flag, so Creating Talkfiles ends at the next possible position
453//!
454void TalkFileCreator::abort()
455{
456 m_abort = true;
457}
458
diff --git a/rbutil/rbutilqt/voicefile.cpp b/rbutil/rbutilqt/voicefile.cpp
deleted file mode 100644
index 4de9b87f34..0000000000
--- a/rbutil/rbutilqt/voicefile.cpp
+++ /dev/null
@@ -1,301 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2007 by Dominik Wenger
10 * $Id$
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#include "utils.h"
22#include "rbsettings.h"
23
24#define STATE_INVALID 0
25#define STATE_PHRASE 1
26#define STATE_VOICE 2
27
28
29VoiceFileCreator::VoiceFileCreator(QObject* parent) :QObject(parent)
30{
31 m_wavtrimThreshold=500;
32}
33
34void VoiceFileCreator::abort()
35{
36 m_abort = true;
37}
38
39bool VoiceFileCreator::createVoiceFile(ProgressloggerInterface* logger)
40{
41 m_abort = false;
42 m_logger = logger;
43 m_logger->addItem(tr("Starting Voicefile generation"),LOGINFO);
44
45 // test if tempdir exists
46 if(!QDir(QDir::tempPath()+"/rbvoice/").exists())
47 {
48 QDir(QDir::tempPath()).mkdir("rbvoice");
49 }
50
51 m_path = QDir::tempPath() + "/rbvoice/";
52
53 // read rockbox-info.txt
54 RockboxInfo info(m_mountpoint);
55 if(!info.open())
56 {
57 m_logger->addItem(tr("could not find rockbox-info.txt"),LOGERROR);
58 m_logger->setFinished();
59 emit done(false);
60 return false;
61 }
62
63 QString target = info.target();
64 QString features = info.features();
65 QString version = info.version();
66 version = version.left(version.indexOf("-")).remove(0,1);
67
68 //prepare download url
69 QUrl genlangUrl = RbSettings::value(RbSettings::GenlangUrl).toString()
70 +"?lang=" + m_lang + "&t=" + target + "&rev=" + version + "&f=" + features;
71
72 qDebug() << "downloading " << genlangUrl;
73
74 //download the correct genlang output
75 QTemporaryFile *downloadFile = new QTemporaryFile(this);
76 downloadFile->open();
77 filename = downloadFile->fileName();
78 downloadFile->close();
79 // get the real file.
80 getter = new HttpGet(this);
81 getter->setFile(downloadFile);
82
83 connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
84 connect(getter, SIGNAL(dataReadProgress(int, int)), this, SLOT(updateDataReadProgress(int, int)));
85 connect(m_logger, SIGNAL(aborted()), getter, SLOT(abort()));
86
87 getter->getFile(genlangUrl);
88 return true;
89 }
90
91
92void VoiceFileCreator::downloadDone(bool error)
93{
94 qDebug() << "Voice creator::downloadDone, error:" << error;
95
96 // update progress bar
97 int max = m_logger->getProgressMax();
98 if(max == 0) {
99 max = 100;
100 m_logger->setProgressMax(max);
101 }
102 m_logger->setProgressValue(max);
103 if(getter->httpResponse() != 200 && !getter->isCached()) {
104 m_logger->addItem(tr("Download error: received HTTP error %1.").arg(getter->httpResponse()),LOGERROR);
105 m_logger->setFinished();
106 emit done(false);
107 return;
108 }
109 if(getter->isCached()) m_logger->addItem(tr("Cached file used."), LOGINFO);
110 if(error) {
111 m_logger->addItem(tr("Download error: %1").arg(getter->errorString()),LOGERROR);
112 m_logger->setFinished();
113 emit done(false);
114 return;
115 }
116 else m_logger->addItem(tr("Download finished."),LOGOK);
117 QCoreApplication::processEvents();
118
119
120 m_logger->setProgressMax(0);
121 //open downloaded file
122 QFile genlang(filename);
123 if(!genlang.open(QIODevice::ReadOnly))
124 {
125 m_logger->addItem(tr("failed to open downloaded file"),LOGERROR);
126 m_logger->setFinished();
127 emit done(false);
128 return;
129 }
130
131 //tts
132 m_tts = TTSBase::getTTS(this,RbSettings::value(RbSettings::Tts).toString());
133
134 QString errStr;
135 if(!m_tts->start(&errStr))
136 {
137 m_logger->addItem(errStr,LOGERROR);
138 m_logger->addItem(tr("Init of TTS engine failed"),LOGERROR);
139 m_logger->setFinished();
140 emit done(false);
141 return;
142 }
143
144 // Encoder
145 m_enc = EncBase::getEncoder(this,RbSettings::value(RbSettings::CurEncoder).toString());
146
147 if(!m_enc->start())
148 {
149 m_logger->addItem(tr("Init of Encoder engine failed"),LOGERROR);
150 m_tts->stop();
151 m_logger->setFinished();
152 emit done(false);
153 return;
154 }
155
156 QCoreApplication::processEvents();
157 connect(m_logger,SIGNAL(aborted()),this,SLOT(abort()));
158
159 //read in downloaded file
160 QList<QPair<QString,QString> > voicepairs;
161 QTextStream in(&genlang);
162 in.setCodec("UTF-8");
163 QString id, voice;
164 bool idfound = false;
165 bool voicefound=false;
166 while (!in.atEnd())
167 {
168 QString line = in.readLine();
169 if(line.contains("id:")) //ID found
170 {
171 id = line.remove("id:").remove('"').trimmed();
172 idfound = true;
173 }
174 else if(line.contains("voice:")) // voice found
175 {
176 voice = line.remove("voice:").remove('"').trimmed();
177 voicefound=true;
178 }
179
180 if(idfound && voicefound)
181 {
182 voicepairs.append(QPair<QString,QString>(id,voice));
183 idfound=false;
184 voicefound=false;
185 }
186 }
187 genlang.close();
188
189 // check for empty list
190 if(voicepairs.size() == 0)
191 {
192 m_logger->addItem(tr("The downloaded file was empty!"),LOGERROR);
193 m_logger->setFinished();
194 m_tts->stop();
195 emit done(false);
196 return;
197 }
198
199 m_logger->setProgressMax(voicepairs.size());
200 m_logger->setProgressValue(0);
201
202 // create voice clips
203 QStringList mp3files;
204 for(int i=0; i< voicepairs.size(); i++)
205 {
206 if(m_abort)
207 {
208 m_logger->addItem("aborted.",LOGERROR);
209 m_logger->setFinished();
210 m_tts->stop();
211 emit done(false);
212 return;
213 }
214
215 m_logger->setProgressValue(i);
216
217 QString wavname = m_path + "/" + voicepairs.at(i).first + ".wav";
218 QString toSpeak = voicepairs.at(i).second;
219 QString encodedname = m_path + "/" + voicepairs.at(i).first +".mp3";
220
221 // todo PAUSE
222 if(voicepairs.at(i).first == "VOICE_PAUSE")
223 {
224 QFile::copy(":/builtin/builtin/VOICE_PAUSE.wav",m_path + "/VOICE_PAUSE.wav");
225
226 }
227 else
228 {
229 if(toSpeak == "") continue;
230
231 m_logger->addItem(tr("creating ")+toSpeak,LOGINFO);
232 QCoreApplication::processEvents();
233
234 // TODO: add support for aborting the operation
235 QString errStr;
236 m_tts->voice(toSpeak,wavname, &errStr); // generate wav
237 }
238
239 // todo strip
240 char buffer[255];
241
242 wavtrim((char*)qPrintable(wavname),m_wavtrimThreshold,buffer,255);
243
244 // encode wav
245 m_enc->encode(wavname,encodedname);
246 // remove the wav file
247 QFile::remove(wavname);
248 // remember the mp3 file for later removing
249 mp3files << encodedname;
250 }
251
252
253 //make voicefile
254 FILE* ids2 = fopen(filename.toUtf8(), "r");
255 if (ids2 == NULL)
256 {
257 m_logger->addItem(tr("Error opening downloaded file"),LOGERROR);
258 m_logger->setFinished();
259 emit done(false);
260 return;
261 }
262
263 FILE* output = fopen(QString(m_mountpoint + "/.rockbox/langs/" + m_lang + ".voice").toUtf8(), "wb");
264 if (output == NULL)
265 {
266 m_logger->addItem(tr("Error opening output file"),LOGERROR);
267 emit done(false);
268 return;
269 }
270
271 voicefont(ids2,m_targetid,(char*)(const char*)m_path.toUtf8(), output);
272
273 //remove .mp3 files
274 for(int i=0;i< mp3files.size(); i++)
275 {
276 QFile::remove(mp3files.at(i));
277 }
278
279 // Add Voice file to the install log
280 QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
281 installlog.beginGroup("selfcreated Voice");
282 installlog.setValue("/.rockbox/langs/" + m_lang + ".voice",QDate::currentDate().toString("yyyyMMdd"));
283 installlog.endGroup();
284 installlog.sync();
285
286 m_logger->setProgressMax(100);
287 m_logger->setProgressValue(100);
288 m_logger->addItem(tr("successfully created."),LOGOK);
289 m_logger->setFinished();
290
291 emit done(true);
292}
293
294void VoiceFileCreator::updateDataReadProgress(int read, int total)
295{
296 m_logger->setProgressMax(total);
297 m_logger->setProgressValue(read);
298 //qDebug() << "progress:" << read << "/" << total;
299
300}
301