forked from len0rd/rockbox
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
This commit is contained in:
parent
73d25744fb
commit
20bf8aaf18
11 changed files with 874 additions and 802 deletions
263
rbutil/rbutilqt/base/talkfile.cpp
Normal file
263
rbutil/rbutilqt/base/talkfile.cpp
Normal file
|
|
@ -0,0 +1,263 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 by Dominik Wenger
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "talkfile.h"
|
||||||
|
#include "rbsettings.h"
|
||||||
|
|
||||||
|
TalkFileCreator::TalkFileCreator(QObject* parent): QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Creates Talkfiles.
|
||||||
|
//!
|
||||||
|
//! \param logger A pointer to a Loggerobject
|
||||||
|
bool TalkFileCreator::createTalkFiles()
|
||||||
|
{
|
||||||
|
m_abort = false;
|
||||||
|
QString errStr;
|
||||||
|
|
||||||
|
emit logItem(tr("Starting Talk file generation"),LOGINFO);
|
||||||
|
emit logProgress(0,0);
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
// read in Maps of paths - file/dirnames
|
||||||
|
emit logItem(tr("Reading Filelist..."),LOGINFO);
|
||||||
|
if(createTalkList(m_dir) == false)
|
||||||
|
{
|
||||||
|
emit logItem(tr("Talk file creation aborted"),LOGERROR);
|
||||||
|
doAbort();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
// generate entries
|
||||||
|
{
|
||||||
|
TalkGenerator generator(this);
|
||||||
|
connect(&generator,SIGNAL(done(bool)),this,SIGNAL(done(bool)));
|
||||||
|
connect(&generator,SIGNAL(logItem(QString,int)),this,SIGNAL(logItem(QString,int)));
|
||||||
|
connect(&generator,SIGNAL(logProgress(int,int)),this,SIGNAL(logProgress(int,int)));
|
||||||
|
connect(this,SIGNAL(aborted()),&generator,SLOT(abort()));
|
||||||
|
|
||||||
|
if(generator.process(&m_talkList) == TalkGenerator::eERROR)
|
||||||
|
{
|
||||||
|
doAbort();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copying talk files
|
||||||
|
emit logItem(tr("Copying Talkfiles..."),LOGINFO);
|
||||||
|
if(copyTalkFiles(&errStr) == false)
|
||||||
|
{
|
||||||
|
emit logItem(errStr,LOGERROR);
|
||||||
|
doAbort();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deleting left overs
|
||||||
|
if( !cleanup())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
emit logItem(tr("Finished creating Talk files"),LOGOK);
|
||||||
|
emit logProgress(1,1);
|
||||||
|
emit done(false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Strips everything after and including the last dot in a string. If there is no dot, nothing is changed
|
||||||
|
//!
|
||||||
|
//! \param filename The filename from which to strip the Extension
|
||||||
|
//! \returns the modified string
|
||||||
|
QString TalkFileCreator::stripExtension(QString filename)
|
||||||
|
{
|
||||||
|
if(filename.lastIndexOf(".") != -1)
|
||||||
|
return filename.left(filename.lastIndexOf("."));
|
||||||
|
else
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Does needed Tasks when we need to abort. Cleans up Files. Stops the Logger, Stops TTS and Encoder
|
||||||
|
//!
|
||||||
|
void TalkFileCreator::doAbort()
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
emit logProgress(0,1);
|
||||||
|
emit done(true);
|
||||||
|
}
|
||||||
|
//! \brief creates a list of what to generate
|
||||||
|
//!
|
||||||
|
//! \param startDir The directory from which to start scanning
|
||||||
|
bool TalkFileCreator::createTalkList(QDir startDir)
|
||||||
|
{
|
||||||
|
m_talkList.clear();
|
||||||
|
|
||||||
|
// create Iterator
|
||||||
|
QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags;
|
||||||
|
if(m_recursive)
|
||||||
|
flags = QDirIterator::Subdirectories;
|
||||||
|
|
||||||
|
QDirIterator it(startDir,flags);
|
||||||
|
|
||||||
|
//create temp directory
|
||||||
|
QDir tempDir(QDir::tempPath()+ "/talkfiles/");
|
||||||
|
if(!tempDir.exists())
|
||||||
|
tempDir.mkpath(QDir::tempPath()+ "/talkfiles/");
|
||||||
|
|
||||||
|
// read in Maps of paths - file/dirnames
|
||||||
|
while (it.hasNext())
|
||||||
|
{
|
||||||
|
it.next();
|
||||||
|
if(m_abort)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFileInfo fileInf = it.fileInfo();
|
||||||
|
|
||||||
|
// its a dir
|
||||||
|
if(fileInf.isDir())
|
||||||
|
{
|
||||||
|
QDir dir = fileInf.dir();
|
||||||
|
|
||||||
|
// insert into List
|
||||||
|
if(!dir.dirName().isEmpty() && m_talkFolders)
|
||||||
|
{
|
||||||
|
TalkGenerator::TalkEntry entry;
|
||||||
|
entry.toSpeak = dir.dirName();
|
||||||
|
entry.wavfilename = QDir::tempPath()+ "/talkfiles/" + QCryptographicHash::hash(entry.toSpeak.toUtf8(),
|
||||||
|
QCryptographicHash::Md5).toHex() + ".wav";
|
||||||
|
entry.talkfilename = QDir::tempPath()+ "/talkfiles/" + QCryptographicHash::hash(entry.toSpeak.toUtf8(),
|
||||||
|
QCryptographicHash::Md5).toHex() + ".talk";
|
||||||
|
entry.target = dir.path() + "/_dirname.talk";
|
||||||
|
entry.voiced = false;
|
||||||
|
entry.encoded = false;
|
||||||
|
qDebug() << "toSpeak: " << entry.toSpeak << " target: " << entry.target << " intermediates: " <<
|
||||||
|
entry.wavfilename << entry.talkfilename;
|
||||||
|
m_talkList.append(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // its a File
|
||||||
|
{
|
||||||
|
// insert into List
|
||||||
|
if( !fileInf.fileName().isEmpty() && !fileInf.fileName().endsWith(".talk") && m_talkFiles)
|
||||||
|
{
|
||||||
|
TalkGenerator::TalkEntry entry;
|
||||||
|
if(m_stripExtensions)
|
||||||
|
entry.toSpeak = stripExtension(fileInf.fileName());
|
||||||
|
else
|
||||||
|
entry.toSpeak = fileInf.fileName();
|
||||||
|
entry.wavfilename = QDir::tempPath()+ "/talkfiles/" + QCryptographicHash::hash(entry.toSpeak.toUtf8(),
|
||||||
|
QCryptographicHash::Md5).toHex() + ".wav";
|
||||||
|
entry.talkfilename = QDir::tempPath()+ "/talkfiles/" + QCryptographicHash::hash(entry.toSpeak.toUtf8(),
|
||||||
|
QCryptographicHash::Md5).toHex() + ".talk";
|
||||||
|
entry.target = fileInf.path() + "/" + fileInf.fileName() + ".talk";
|
||||||
|
entry.voiced = false;
|
||||||
|
entry.encoded = false;
|
||||||
|
qDebug() << "toSpeak: " << entry.toSpeak << " target: " << entry.target << " intermediates: " <<
|
||||||
|
entry.wavfilename << entry.talkfilename;
|
||||||
|
m_talkList.append(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \brief copys Talkfiles from the temp dir to the target. Progress and installlog is handled inside
|
||||||
|
//!
|
||||||
|
//! \param errString Pointer to a QString where the error cause is written.
|
||||||
|
//! \returns true on success, false on error or user abort
|
||||||
|
bool TalkFileCreator::copyTalkFiles(QString* errString)
|
||||||
|
{
|
||||||
|
int progressMax = m_talkList.size();
|
||||||
|
int m_progress = 0;
|
||||||
|
emit logProgress(m_progress,progressMax);
|
||||||
|
|
||||||
|
QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
|
||||||
|
installlog.beginGroup("talkfiles");
|
||||||
|
|
||||||
|
for(int i=0; i < m_talkList.size(); i++)
|
||||||
|
{
|
||||||
|
if(m_abort)
|
||||||
|
{
|
||||||
|
*errString = tr("File copy aborted");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip not encoded files
|
||||||
|
if(m_talkList[i].encoded == false)
|
||||||
|
{
|
||||||
|
emit logProgress(++m_progress,progressMax);
|
||||||
|
continue; // this file was skipped in one of the previous steps
|
||||||
|
}
|
||||||
|
// remove target if it exists, and if we should overwrite it
|
||||||
|
if(m_overwriteTalk && QFile::exists(m_talkList[i].target))
|
||||||
|
QFile::remove(m_talkList[i].target);
|
||||||
|
|
||||||
|
// copying
|
||||||
|
qDebug() << "copying " << m_talkList[i].talkfilename << "to" << m_talkList[i].target;
|
||||||
|
if(!QFile::copy(m_talkList[i].talkfilename,m_talkList[i].target))
|
||||||
|
{
|
||||||
|
*errString = tr("Copying of %1 to %2 failed").arg(m_talkList[i].talkfilename).arg(m_talkList[i].target);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add to installlog
|
||||||
|
QString now = QDate::currentDate().toString("yyyyMMdd");
|
||||||
|
installlog.setValue(m_talkList[i].target.remove(0,m_mountpoint.length()),now);
|
||||||
|
|
||||||
|
emit logProgress(++m_progress,progressMax);
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
installlog.endGroup();
|
||||||
|
installlog.sync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \brief Cleans up Files potentially left in the temp dir
|
||||||
|
//!
|
||||||
|
bool TalkFileCreator::cleanup()
|
||||||
|
{
|
||||||
|
emit logItem(tr("Cleaning up.."),LOGINFO);
|
||||||
|
|
||||||
|
for(int i=0; i < m_talkList.size(); i++)
|
||||||
|
{
|
||||||
|
if(QFile::exists(m_talkList[i].wavfilename))
|
||||||
|
QFile::remove(m_talkList[i].wavfilename);
|
||||||
|
if(QFile::exists(m_talkList[i].talkfilename))
|
||||||
|
QFile::remove(m_talkList[i].talkfilename);
|
||||||
|
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
emit logItem(tr("Finished"),LOGINFO);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief slot, which is connected to the abort of the Logger. Sets a flag, so Creating Talkfiles ends at the next possible position
|
||||||
|
//!
|
||||||
|
void TalkFileCreator::abort()
|
||||||
|
{
|
||||||
|
m_abort = true;
|
||||||
|
emit aborted();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -26,8 +26,7 @@
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include "progressloggerinterface.h"
|
#include "progressloggerinterface.h"
|
||||||
|
|
||||||
#include "encoders.h"
|
#include "talkgenerator.h"
|
||||||
#include "tts.h"
|
|
||||||
|
|
||||||
class TalkFileCreator :public QObject
|
class TalkFileCreator :public QObject
|
||||||
{
|
{
|
||||||
|
|
@ -36,7 +35,7 @@ class TalkFileCreator :public QObject
|
||||||
public:
|
public:
|
||||||
TalkFileCreator(QObject* parent);
|
TalkFileCreator(QObject* parent);
|
||||||
|
|
||||||
bool createTalkFiles(ProgressloggerInterface* logger);
|
bool createTalkFiles();
|
||||||
|
|
||||||
void setDir(QDir dir){m_dir = dir; }
|
void setDir(QDir dir){m_dir = dir; }
|
||||||
void setMountPoint(QString mountpoint) {m_mountpoint =mountpoint; }
|
void setMountPoint(QString mountpoint) {m_mountpoint =mountpoint; }
|
||||||
|
|
@ -47,26 +46,26 @@ public:
|
||||||
void setTalkFolders(bool ov) {m_talkFolders = ov;}
|
void setTalkFolders(bool ov) {m_talkFolders = ov;}
|
||||||
void setTalkFiles(bool ov) {m_talkFiles = ov;}
|
void setTalkFiles(bool ov) {m_talkFiles = ov;}
|
||||||
|
|
||||||
private slots:
|
public slots:
|
||||||
void abort();
|
void abort();
|
||||||
|
|
||||||
private:
|
|
||||||
bool cleanup(QStringList list);
|
|
||||||
QString stripExtension(QString filename);
|
|
||||||
void doAbort(QStringList cleanupList);
|
|
||||||
void resetProgress(int max);
|
|
||||||
bool createDirAndFileMaps(QDir startDir,QMultiMap<QString,QString> *dirMap,QMultiMap<QString,QString> *fileMap);
|
|
||||||
TTSStatus voiceList(QStringList toSpeak,QStringList& voicedEntries);
|
|
||||||
bool encodeList(QStringList toEncode,QStringList& encodedEntries);
|
|
||||||
bool copyTalkDirFiles(QMultiMap<QString,QString> dirMap,QString* errString);
|
|
||||||
bool copyTalkFileFiles(QMultiMap<QString,QString> fileMap,QString* errString);
|
|
||||||
|
|
||||||
TTSBase* m_tts;
|
signals:
|
||||||
EncBase* m_enc;
|
void done(bool);
|
||||||
|
void aborted();
|
||||||
|
void logItem(QString, int); //! set logger item
|
||||||
|
void logProgress(int, int); //! set progress bar.
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool cleanup();
|
||||||
|
QString stripExtension(QString filename);
|
||||||
|
void doAbort();
|
||||||
|
void resetProgress(int max);
|
||||||
|
bool copyTalkFiles(QString* errString);
|
||||||
|
|
||||||
|
bool createTalkList(QDir startDir);
|
||||||
|
|
||||||
QDir m_dir;
|
QDir m_dir;
|
||||||
QString m_mountpoint;
|
QString m_mountpoint;
|
||||||
int m_progress;
|
|
||||||
|
|
||||||
bool m_overwriteTalk;
|
bool m_overwriteTalk;
|
||||||
bool m_recursive;
|
bool m_recursive;
|
||||||
|
|
@ -74,9 +73,9 @@ private:
|
||||||
bool m_talkFolders;
|
bool m_talkFolders;
|
||||||
bool m_talkFiles;
|
bool m_talkFiles;
|
||||||
|
|
||||||
ProgressloggerInterface* m_logger;
|
|
||||||
|
|
||||||
bool m_abort;
|
bool m_abort;
|
||||||
|
|
||||||
|
QList<TalkGenerator::TalkEntry> m_talkList;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
238
rbutil/rbutilqt/base/talkgenerator.cpp
Normal file
238
rbutil/rbutilqt/base/talkgenerator.cpp
Normal file
|
|
@ -0,0 +1,238 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 by Dominik Wenger
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "talkgenerator.h"
|
||||||
|
#include "rbsettings.h"
|
||||||
|
#include "wavtrim.h"
|
||||||
|
|
||||||
|
TalkGenerator::TalkGenerator(QObject* parent): QObject(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Creates Talkfiles.
|
||||||
|
//!
|
||||||
|
TalkGenerator::Status TalkGenerator::process(QList<TalkEntry>* list,int wavtrimth)
|
||||||
|
{
|
||||||
|
m_abort = false;
|
||||||
|
QString errStr;
|
||||||
|
bool warnings = false;
|
||||||
|
|
||||||
|
//tts
|
||||||
|
emit logItem(tr("Starting TTS Engine"),LOGINFO);
|
||||||
|
m_tts = TTSBase::getTTS(this,RbSettings::value(RbSettings::Tts).toString());
|
||||||
|
if(!m_tts->start(&errStr))
|
||||||
|
{
|
||||||
|
emit logItem(errStr.trimmed(),LOGERROR);
|
||||||
|
emit logItem(tr("Init of TTS engine failed"),LOGERROR);
|
||||||
|
emit done(true);
|
||||||
|
return eERROR;
|
||||||
|
}
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
// Encoder
|
||||||
|
emit logItem(tr("Starting Encoder Engine"),LOGINFO);
|
||||||
|
m_enc = EncBase::getEncoder(this,RbSettings::value(RbSettings::CurEncoder).toString());
|
||||||
|
if(!m_enc->start())
|
||||||
|
{
|
||||||
|
emit logItem(tr("Init of Encoder engine failed"),LOGERROR);
|
||||||
|
emit done(true);
|
||||||
|
m_tts->stop();
|
||||||
|
return eERROR;
|
||||||
|
}
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
emit logProgress(0,0);
|
||||||
|
|
||||||
|
// Voice entries
|
||||||
|
emit logItem(tr("Voicing entries..."),LOGINFO);
|
||||||
|
Status voiceStatus= voiceList(list,wavtrimth);
|
||||||
|
if(voiceStatus == eERROR)
|
||||||
|
{
|
||||||
|
m_tts->stop();
|
||||||
|
m_enc->stop();
|
||||||
|
emit done(true);
|
||||||
|
return eERROR;
|
||||||
|
}
|
||||||
|
else if( voiceStatus == eWARNING)
|
||||||
|
warnings = true;
|
||||||
|
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
// Encoding Entries
|
||||||
|
emit logItem(tr("Encoding files..."),LOGINFO);
|
||||||
|
Status encoderStatus = encodeList(list);
|
||||||
|
if( encoderStatus == eERROR)
|
||||||
|
{
|
||||||
|
m_tts->stop();
|
||||||
|
m_enc->stop();
|
||||||
|
emit done(true);
|
||||||
|
return eERROR;
|
||||||
|
}
|
||||||
|
else if( voiceStatus == eWARNING)
|
||||||
|
warnings = true;
|
||||||
|
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
m_tts->stop();
|
||||||
|
m_enc->stop();
|
||||||
|
emit logProgress(1,1);
|
||||||
|
|
||||||
|
if(warnings)
|
||||||
|
return eWARNING;
|
||||||
|
return eOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Voices a List of string
|
||||||
|
//!
|
||||||
|
TalkGenerator::Status TalkGenerator::voiceList(QList<TalkEntry>* list,int wavtrimth)
|
||||||
|
{
|
||||||
|
int progressMax = list->size();
|
||||||
|
int m_progress = 0;
|
||||||
|
emit logProgress(m_progress,progressMax);
|
||||||
|
|
||||||
|
QStringList errors;
|
||||||
|
QStringList dublicates;
|
||||||
|
|
||||||
|
bool warnings = false;
|
||||||
|
for(int i=0; i < list->size(); i++)
|
||||||
|
{
|
||||||
|
if(m_abort)
|
||||||
|
{
|
||||||
|
emit logItem(tr("Voicing aborted"), LOGERROR);
|
||||||
|
return eERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip dublicated wav entrys
|
||||||
|
if(!dublicates.contains(list->at(i).wavfilename))
|
||||||
|
dublicates.append(list->at(i).wavfilename);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "dublicate skipped";
|
||||||
|
(*list)[i].voiced = true;
|
||||||
|
emit logProgress(++m_progress,progressMax);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip already voiced entrys
|
||||||
|
if(list->at(i).voiced == true)
|
||||||
|
{
|
||||||
|
emit logProgress(++m_progress,progressMax);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// skip entry whith empty text
|
||||||
|
if(list->at(i).toSpeak == "")
|
||||||
|
{
|
||||||
|
emit logProgress(++m_progress,progressMax);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// voice entry
|
||||||
|
QString error;
|
||||||
|
qDebug() << "voicing: " << list->at(i).toSpeak << "to" << list->at(i).wavfilename;
|
||||||
|
TTSStatus status = m_tts->voice(list->at(i).toSpeak,list->at(i).wavfilename, &error);
|
||||||
|
if(status == Warning)
|
||||||
|
{
|
||||||
|
warnings = true;
|
||||||
|
emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error),
|
||||||
|
LOGWARNING);
|
||||||
|
}
|
||||||
|
else if (status == FatalError)
|
||||||
|
{
|
||||||
|
emit logItem(tr("Voicing of %1 failed: %2").arg(list->at(i).toSpeak).arg(error),
|
||||||
|
LOGERROR);
|
||||||
|
return eERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
(*list)[i].voiced = true;
|
||||||
|
|
||||||
|
//wavetrim if needed
|
||||||
|
if(wavtrimth != -1)
|
||||||
|
{
|
||||||
|
char buffer[255];
|
||||||
|
wavtrim(list->at(i).wavfilename.toLocal8Bit().data(),wavtrimth,buffer,255);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit logProgress(++m_progress,progressMax);
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
if(warnings)
|
||||||
|
return eWARNING;
|
||||||
|
else
|
||||||
|
return eOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! \brief Encodes a List of strings
|
||||||
|
//!
|
||||||
|
TalkGenerator::Status TalkGenerator::encodeList(QList<TalkEntry>* list)
|
||||||
|
{
|
||||||
|
QStringList dublicates;
|
||||||
|
|
||||||
|
int progressMax = list->size();
|
||||||
|
int m_progress = 0;
|
||||||
|
emit logProgress(m_progress,progressMax);
|
||||||
|
|
||||||
|
for(int i=0; i < list->size(); i++)
|
||||||
|
{
|
||||||
|
if(m_abort)
|
||||||
|
{
|
||||||
|
emit logItem(tr("Encoding aborted"), LOGERROR);
|
||||||
|
return eERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
//skip non-voiced entrys
|
||||||
|
if(list->at(i).voiced == false)
|
||||||
|
{
|
||||||
|
qDebug() << "non voiced entry" << list->at(i).toSpeak <<"detected";
|
||||||
|
emit logProgress(++m_progress,progressMax);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//skip dublicates
|
||||||
|
if(!dublicates.contains(list->at(i).talkfilename))
|
||||||
|
dublicates.append(list->at(i).talkfilename);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "dublicate skipped";
|
||||||
|
(*list)[i].encoded = true;
|
||||||
|
emit logProgress(++m_progress,progressMax);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//encode entry
|
||||||
|
qDebug() << "encoding " << list->at(i).wavfilename << "to" << list->at(i).talkfilename;
|
||||||
|
if(!m_enc->encode(list->at(i).wavfilename,list->at(i).talkfilename))
|
||||||
|
{
|
||||||
|
emit logItem(tr("Encoding of %1 failed").arg(list->at(i).wavfilename), LOGERROR);
|
||||||
|
return eERROR;
|
||||||
|
}
|
||||||
|
(*list)[i].encoded = true;
|
||||||
|
emit logProgress(++m_progress,progressMax);
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
return eOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief slot, which is connected to the abort of the Logger. Sets a flag, so Creating Talkfiles ends at the next possible position
|
||||||
|
//!
|
||||||
|
void TalkGenerator::abort()
|
||||||
|
{
|
||||||
|
m_abort = true;
|
||||||
|
}
|
||||||
|
|
||||||
78
rbutil/rbutilqt/base/talkgenerator.h
Normal file
78
rbutil/rbutilqt/base/talkgenerator.h
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 by Dominik Wenger
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TALKGENERATOR_H
|
||||||
|
#define TALKGENERATOR_H
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
#include "progressloggerinterface.h"
|
||||||
|
|
||||||
|
#include "encoders.h"
|
||||||
|
#include "tts.h"
|
||||||
|
|
||||||
|
//! \brief Talk generator, generates .wav and .talk files out of a list.
|
||||||
|
class TalkGenerator :public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum Status
|
||||||
|
{
|
||||||
|
eOK,
|
||||||
|
eWARNING,
|
||||||
|
eERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TalkEntry
|
||||||
|
{
|
||||||
|
QString toSpeak;
|
||||||
|
QString wavfilename;
|
||||||
|
QString talkfilename;
|
||||||
|
QString target;
|
||||||
|
bool voiced;
|
||||||
|
bool encoded;
|
||||||
|
};
|
||||||
|
|
||||||
|
TalkGenerator(QObject* parent);
|
||||||
|
|
||||||
|
Status process(QList<TalkEntry>* list,int wavtrimth = -1);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void abort();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void done(bool);
|
||||||
|
void logItem(QString, int); //! set logger item
|
||||||
|
void logProgress(int, int); //! set progress bar.
|
||||||
|
|
||||||
|
private:
|
||||||
|
Status voiceList(QList<TalkEntry>* list,int wavetrimth);
|
||||||
|
Status encodeList(QList<TalkEntry>* list);
|
||||||
|
|
||||||
|
TTSBase* m_tts;
|
||||||
|
EncBase* m_enc;
|
||||||
|
|
||||||
|
bool m_abort;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
246
rbutil/rbutilqt/base/voicefile.cpp
Normal file
246
rbutil/rbutilqt/base/voicefile.cpp
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 by Dominik Wenger
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "voicefile.h"
|
||||||
|
#include "utils.h"
|
||||||
|
#include "rbsettings.h"
|
||||||
|
|
||||||
|
VoiceFileCreator::VoiceFileCreator(QObject* parent) :QObject(parent)
|
||||||
|
{
|
||||||
|
m_wavtrimThreshold=500;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoiceFileCreator::abort()
|
||||||
|
{
|
||||||
|
m_abort = true;
|
||||||
|
emit aborted();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoiceFileCreator::createVoiceFile()
|
||||||
|
{
|
||||||
|
m_talkList.clear();
|
||||||
|
m_abort = false;
|
||||||
|
emit logItem(tr("Starting Voicefile generation"),LOGINFO);
|
||||||
|
|
||||||
|
// test if tempdir exists
|
||||||
|
if(!QDir(QDir::tempPath()+"/rbvoice/").exists())
|
||||||
|
{
|
||||||
|
QDir(QDir::tempPath()).mkdir("rbvoice");
|
||||||
|
}
|
||||||
|
m_path = QDir::tempPath() + "/rbvoice/";
|
||||||
|
|
||||||
|
// read rockbox-info.txt
|
||||||
|
RockboxInfo info(m_mountpoint);
|
||||||
|
if(!info.open())
|
||||||
|
{
|
||||||
|
emit logItem(tr("could not find rockbox-info.txt"),LOGERROR);
|
||||||
|
emit done(true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString target = info.target();
|
||||||
|
QString features = info.features();
|
||||||
|
QString version = info.version();
|
||||||
|
version = version.left(version.indexOf("-")).remove(0,1);
|
||||||
|
|
||||||
|
//prepare download url
|
||||||
|
QUrl genlangUrl = RbSettings::value(RbSettings::GenlangUrl).toString()
|
||||||
|
+"?lang=" + m_lang + "&t=" + target + "&rev=" + version + "&f=" + features;
|
||||||
|
|
||||||
|
qDebug() << "downloading " << genlangUrl;
|
||||||
|
|
||||||
|
//download the correct genlang output
|
||||||
|
QTemporaryFile *downloadFile = new QTemporaryFile(this);
|
||||||
|
downloadFile->open();
|
||||||
|
filename = downloadFile->fileName();
|
||||||
|
downloadFile->close();
|
||||||
|
// get the real file.
|
||||||
|
getter = new HttpGet(this);
|
||||||
|
getter->setFile(downloadFile);
|
||||||
|
|
||||||
|
connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
|
||||||
|
connect(getter, SIGNAL(dataReadProgress(int, int)), this, SIGNAL(logProgress(int, int)));
|
||||||
|
connect(this, SIGNAL(aborted()), getter, SLOT(abort()));
|
||||||
|
emit logItem(tr("Downloading voice info.."),LOGINFO);
|
||||||
|
getter->getFile(genlangUrl);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VoiceFileCreator::downloadDone(bool error)
|
||||||
|
{
|
||||||
|
qDebug() << "Voice creator::downloadDone, error:" << error;
|
||||||
|
|
||||||
|
// update progress bar
|
||||||
|
emit logProgress(1,1);
|
||||||
|
if(getter->httpResponse() != 200 && !getter->isCached()) {
|
||||||
|
emit logItem(tr("Download error: received HTTP error %1.").arg(getter->httpResponse()),LOGERROR);
|
||||||
|
emit done(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(getter->isCached())
|
||||||
|
emit logItem(tr("Cached file used."), LOGINFO);
|
||||||
|
if(error)
|
||||||
|
{
|
||||||
|
emit logItem(tr("Download error: %1").arg(getter->errorString()),LOGERROR);
|
||||||
|
emit done(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
emit logItem(tr("Download finished."),LOGINFO);
|
||||||
|
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
//open downloaded file
|
||||||
|
QFile genlang(filename);
|
||||||
|
if(!genlang.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
emit logItem(tr("failed to open downloaded file"),LOGERROR);
|
||||||
|
emit done(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
|
||||||
|
//read in downloaded file
|
||||||
|
emit logItem(tr("Reading strings..."),LOGINFO);
|
||||||
|
QTextStream in(&genlang);
|
||||||
|
in.setCodec("UTF-8");
|
||||||
|
QString id, voice;
|
||||||
|
bool idfound = false;
|
||||||
|
bool voicefound=false;
|
||||||
|
while (!in.atEnd())
|
||||||
|
{
|
||||||
|
QString line = in.readLine();
|
||||||
|
if(line.contains("id:")) //ID found
|
||||||
|
{
|
||||||
|
id = line.remove("id:").remove('"').trimmed();
|
||||||
|
idfound = true;
|
||||||
|
}
|
||||||
|
else if(line.contains("voice:")) // voice found
|
||||||
|
{
|
||||||
|
voice = line.remove("voice:").remove('"').trimmed();
|
||||||
|
voicefound=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(idfound && voicefound)
|
||||||
|
{
|
||||||
|
TalkGenerator::TalkEntry entry;
|
||||||
|
entry.toSpeak = voice;
|
||||||
|
entry.wavfilename = m_path + "/" + id + ".wav";
|
||||||
|
entry.talkfilename = m_path + "/" + id + ".mp3"; //voicefont wants them with .mp3 extension
|
||||||
|
entry.voiced = false;
|
||||||
|
entry.encoded = false;
|
||||||
|
if(id == "VOICE_PAUSE")
|
||||||
|
{
|
||||||
|
QFile::copy(":/builtin/VOICE_PAUSE.wav",m_path + "/VOICE_PAUSE.wav");
|
||||||
|
entry.wavfilename = m_path + "/VOICE_PAUSE.wav";
|
||||||
|
entry.voiced = true;
|
||||||
|
}
|
||||||
|
m_talkList.append(entry);
|
||||||
|
idfound=false;
|
||||||
|
voicefound=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
genlang.close();
|
||||||
|
|
||||||
|
// check for empty list
|
||||||
|
if(m_talkList.size() == 0)
|
||||||
|
{
|
||||||
|
emit logItem(tr("The downloaded file was empty!"),LOGERROR);
|
||||||
|
emit done(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate files
|
||||||
|
{
|
||||||
|
TalkGenerator generator(this);
|
||||||
|
connect(&generator,SIGNAL(done(bool)),this,SIGNAL(done(bool)));
|
||||||
|
connect(&generator,SIGNAL(logItem(QString,int)),this,SIGNAL(logItem(QString,int)));
|
||||||
|
connect(&generator,SIGNAL(logProgress(int,int)),this,SIGNAL(logProgress(int,int)));
|
||||||
|
connect(this,SIGNAL(aborted()),&generator,SLOT(abort()));
|
||||||
|
|
||||||
|
if(generator.process(&m_talkList) == TalkGenerator::eERROR)
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
emit logProgress(0,1);
|
||||||
|
emit done(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//make voicefile
|
||||||
|
emit logItem(tr("Creating voicefiles..."),LOGINFO);
|
||||||
|
FILE* ids2 = fopen(filename.toLocal8Bit(), "r");
|
||||||
|
if (ids2 == NULL)
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
emit logItem(tr("Error opening downloaded file"),LOGERROR);
|
||||||
|
emit done(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* output = fopen(QString(m_mountpoint + "/.rockbox/langs/" + m_lang + ".voice").toLocal8Bit(), "wb");
|
||||||
|
if (output == NULL)
|
||||||
|
{
|
||||||
|
cleanup();
|
||||||
|
emit logItem(tr("Error opening output file"),LOGERROR);
|
||||||
|
emit done(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
voicefont(ids2,m_targetid,m_path.toLocal8Bit().data(), output);
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
cleanup();
|
||||||
|
|
||||||
|
// Add Voice file to the install log
|
||||||
|
QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
|
||||||
|
installlog.beginGroup("selfcreated Voice");
|
||||||
|
installlog.setValue("/.rockbox/langs/" + m_lang + ".voice",QDate::currentDate().toString("yyyyMMdd"));
|
||||||
|
installlog.endGroup();
|
||||||
|
installlog.sync();
|
||||||
|
|
||||||
|
emit logProgress(1,1);
|
||||||
|
emit logItem(tr("successfully created."),LOGOK);
|
||||||
|
|
||||||
|
emit done(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief Cleans up Files potentially left in the temp dir
|
||||||
|
//!
|
||||||
|
void VoiceFileCreator::cleanup()
|
||||||
|
{
|
||||||
|
emit logItem(tr("Cleaning up.."),LOGINFO);
|
||||||
|
|
||||||
|
for(int i=0; i < m_talkList.size(); i++)
|
||||||
|
{
|
||||||
|
if(QFile::exists(m_talkList[i].wavfilename))
|
||||||
|
QFile::remove(m_talkList[i].wavfilename);
|
||||||
|
if(QFile::exists(m_talkList[i].talkfilename))
|
||||||
|
QFile::remove(m_talkList[i].talkfilename);
|
||||||
|
|
||||||
|
QCoreApplication::processEvents();
|
||||||
|
}
|
||||||
|
emit logItem(tr("Finished"),LOGINFO);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -26,12 +26,9 @@
|
||||||
#include <QtCore>
|
#include <QtCore>
|
||||||
#include "progressloggerinterface.h"
|
#include "progressloggerinterface.h"
|
||||||
|
|
||||||
#include "encoders.h"
|
|
||||||
#include "tts.h"
|
|
||||||
#include "httpget.h"
|
#include "httpget.h"
|
||||||
|
|
||||||
#include "wavtrim.h"
|
|
||||||
#include "voicefont.h"
|
#include "voicefont.h"
|
||||||
|
#include "talkgenerator.h"
|
||||||
|
|
||||||
class VoiceFileCreator :public QObject
|
class VoiceFileCreator :public QObject
|
||||||
{
|
{
|
||||||
|
|
@ -40,39 +37,38 @@ public:
|
||||||
VoiceFileCreator(QObject* parent);
|
VoiceFileCreator(QObject* parent);
|
||||||
|
|
||||||
//start creation
|
//start creation
|
||||||
bool createVoiceFile(ProgressloggerInterface* logger);
|
bool createVoiceFile();
|
||||||
|
|
||||||
void setMountPoint(QString mountpoint) {m_mountpoint =mountpoint; }
|
void setMountPoint(QString mountpoint) {m_mountpoint =mountpoint; }
|
||||||
void setTargetId(int id){m_targetid = id;}
|
void setTargetId(int id){m_targetid = id;}
|
||||||
void setLang(QString name){m_lang =name;}
|
void setLang(QString name){m_lang =name;}
|
||||||
void setWavtrimThreshold(int th){m_wavtrimThreshold = th;}
|
void setWavtrimThreshold(int th){m_wavtrimThreshold = th;}
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void abort();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void done(bool error);
|
void done(bool);
|
||||||
|
void aborted();
|
||||||
|
void logItem(QString, int); //! set logger item
|
||||||
|
void logProgress(int, int); //! set progress bar.
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void abort();
|
|
||||||
void downloadDone(bool error);
|
void downloadDone(bool error);
|
||||||
void updateDataReadProgress(int read, int total);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void cleanup();
|
||||||
// ptr to encoder, tts and settings
|
|
||||||
TTSBase* m_tts;
|
|
||||||
EncBase* m_enc;
|
|
||||||
HttpGet *getter;
|
HttpGet *getter;
|
||||||
|
|
||||||
QString filename; //the temporary file
|
QString filename; //the temporary file
|
||||||
|
|
||||||
QString m_mountpoint; //mountpoint of the device
|
QString m_mountpoint; //mountpoint of the device
|
||||||
QString m_path; //path where the wav and mp3 files are stored to
|
QString m_path; //path where the wav and mp3 files are stored to
|
||||||
int m_targetid; //the target id
|
int m_targetid; //the target id
|
||||||
QString m_lang; // the language which will be spoken
|
QString m_lang; // the language which will be spoken
|
||||||
int m_wavtrimThreshold;
|
int m_wavtrimThreshold;
|
||||||
|
|
||||||
ProgressloggerInterface* m_logger;
|
|
||||||
|
|
||||||
bool m_abort;
|
bool m_abort;
|
||||||
|
QList<TalkGenerator::TalkEntry> m_talkList;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -60,7 +60,11 @@ void CreateVoiceWindow::accept()
|
||||||
voicecreator->setWavtrimThreshold(wvThreshold);
|
voicecreator->setWavtrimThreshold(wvThreshold);
|
||||||
|
|
||||||
//start creating
|
//start creating
|
||||||
voicecreator->createVoiceFile(logger);
|
connect(voicecreator, SIGNAL(done(bool)), logger, SLOT(setFinished()));
|
||||||
|
connect(voicecreator, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
|
||||||
|
connect(voicecreator, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
|
||||||
|
connect(logger,SIGNAL(aborted()),voicecreator,SLOT(abort()));
|
||||||
|
voicecreator->createVoiceFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,12 @@ void InstallTalkWindow::accept()
|
||||||
talkcreator->setTalkFolders(ui.talkFolders->isChecked());
|
talkcreator->setTalkFolders(ui.talkFolders->isChecked());
|
||||||
talkcreator->setTalkFiles(ui.talkFiles->isChecked());
|
talkcreator->setTalkFiles(ui.talkFiles->isChecked());
|
||||||
|
|
||||||
talkcreator->createTalkFiles(logger);
|
connect(talkcreator, SIGNAL(done(bool)), logger, SLOT(setFinished()));
|
||||||
|
connect(talkcreator, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
|
||||||
|
connect(talkcreator, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
|
||||||
|
connect(logger,SIGNAL(aborted()),talkcreator,SLOT(abort()));
|
||||||
|
|
||||||
|
talkcreator->createTalkFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,8 @@ SOURCES += rbutilqt.cpp \
|
||||||
base/zipinstaller.cpp \
|
base/zipinstaller.cpp \
|
||||||
progressloggergui.cpp \
|
progressloggergui.cpp \
|
||||||
installtalkwindow.cpp \
|
installtalkwindow.cpp \
|
||||||
talkfile.cpp \
|
base/talkfile.cpp \
|
||||||
|
base/talkgenerator.cpp \
|
||||||
base/autodetection.cpp \
|
base/autodetection.cpp \
|
||||||
../ipodpatcher/ipodpatcher.c \
|
../ipodpatcher/ipodpatcher.c \
|
||||||
../sansapatcher/sansapatcher.c \
|
../sansapatcher/sansapatcher.c \
|
||||||
|
|
@ -69,7 +70,7 @@ SOURCES += rbutilqt.cpp \
|
||||||
base/tts.cpp \
|
base/tts.cpp \
|
||||||
../../tools/wavtrim.c \
|
../../tools/wavtrim.c \
|
||||||
../../tools/voicefont.c \
|
../../tools/voicefont.c \
|
||||||
voicefile.cpp \
|
base/voicefile.cpp \
|
||||||
createvoicewindow.cpp \
|
createvoicewindow.cpp \
|
||||||
base/rbsettings.cpp \
|
base/rbsettings.cpp \
|
||||||
base/rbunzip.cpp \
|
base/rbunzip.cpp \
|
||||||
|
|
@ -97,7 +98,8 @@ HEADERS += rbutilqt.h \
|
||||||
version.h \
|
version.h \
|
||||||
base/zipinstaller.h \
|
base/zipinstaller.h \
|
||||||
installtalkwindow.h \
|
installtalkwindow.h \
|
||||||
talkfile.h \
|
base/talkfile.h \
|
||||||
|
base/talkgenerator.h \
|
||||||
base/autodetection.h \
|
base/autodetection.h \
|
||||||
progressloggerinterface.h \
|
progressloggerinterface.h \
|
||||||
progressloggergui.h \
|
progressloggergui.h \
|
||||||
|
|
@ -121,7 +123,7 @@ HEADERS += rbutilqt.h \
|
||||||
base/tts.h \
|
base/tts.h \
|
||||||
../../tools/wavtrim.h \
|
../../tools/wavtrim.h \
|
||||||
../../tools/voicefont.h \
|
../../tools/voicefont.h \
|
||||||
voicefile.h \
|
base/voicefile.h \
|
||||||
createvoicewindow.h \
|
createvoicewindow.h \
|
||||||
base/rbsettings.h \
|
base/rbsettings.h \
|
||||||
base/rbunzip.h \
|
base/rbunzip.h \
|
||||||
|
|
|
||||||
|
|
@ -1,458 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
* __________ __ ___.
|
|
||||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
||||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
||||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
||||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
||||||
* \/ \/ \/ \/ \/
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007 by Dominik Wenger
|
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* All files in this archive are subject to the GNU General Public License.
|
|
||||||
* See the file COPYING in the source tree root for full license agreement.
|
|
||||||
*
|
|
||||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
||||||
* KIND, either express or implied.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "talkfile.h"
|
|
||||||
#include "rbsettings.h"
|
|
||||||
|
|
||||||
TalkFileCreator::TalkFileCreator(QObject* parent): QObject(parent)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \brief Creates Talkfiles.
|
|
||||||
//!
|
|
||||||
//! \param logger A pointer to a Loggerobject
|
|
||||||
bool TalkFileCreator::createTalkFiles(ProgressloggerInterface* logger)
|
|
||||||
{
|
|
||||||
m_abort = false;
|
|
||||||
m_logger = logger;
|
|
||||||
|
|
||||||
QMultiMap<QString,QString> fileList;
|
|
||||||
QMultiMap<QString,QString> dirList;
|
|
||||||
QStringList toSpeakList, voicedEntries, encodedEntries;
|
|
||||||
QString errStr;
|
|
||||||
|
|
||||||
m_logger->addItem(tr("Starting Talk file generation"),LOGINFO);
|
|
||||||
|
|
||||||
//tts
|
|
||||||
m_tts = TTSBase::getTTS(this,RbSettings::value(RbSettings::Tts).toString());
|
|
||||||
|
|
||||||
if(!m_tts->start(&errStr))
|
|
||||||
{
|
|
||||||
m_logger->addItem(errStr.trimmed(),LOGERROR);
|
|
||||||
m_logger->addItem(tr("Init of TTS engine failed"),LOGERROR);
|
|
||||||
m_logger->setFinished();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encoder
|
|
||||||
m_enc = EncBase::getEncoder(this,RbSettings::value(RbSettings::CurEncoder).toString());
|
|
||||||
|
|
||||||
if(!m_enc->start())
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("Init of Encoder engine failed"),LOGERROR);
|
|
||||||
m_logger->setFinished();
|
|
||||||
m_tts->stop();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
|
|
||||||
connect(logger,SIGNAL(aborted()),this,SLOT(abort()));
|
|
||||||
m_logger->setProgressMax(0);
|
|
||||||
|
|
||||||
// read in Maps of paths - file/dirnames
|
|
||||||
m_logger->addItem(tr("Reading Filelist..."),LOGINFO);
|
|
||||||
if(createDirAndFileMaps(m_dir,&dirList,&fileList) == false)
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("Talk file creation aborted"),LOGERROR);
|
|
||||||
doAbort(toSpeakList);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create List of all Files/Dirs to speak
|
|
||||||
QMapIterator<QString, QString> dirIt(dirList);
|
|
||||||
while (dirIt.hasNext())
|
|
||||||
{
|
|
||||||
dirIt.next();
|
|
||||||
// insert only non dublicate dir entries into list
|
|
||||||
if(!toSpeakList.contains(dirIt.value()))
|
|
||||||
{
|
|
||||||
qDebug() << "toSpeaklist dir:" << dirIt.value();
|
|
||||||
toSpeakList.append(dirIt.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QMapIterator<QString, QString> fileIt(fileList);
|
|
||||||
while (fileIt.hasNext())
|
|
||||||
{
|
|
||||||
fileIt.next();
|
|
||||||
// insert only non- dublictae file entries into list
|
|
||||||
if(!toSpeakList.contains(fileIt.value()))
|
|
||||||
{
|
|
||||||
if(m_stripExtensions)
|
|
||||||
toSpeakList.append(stripExtension(fileIt.value()));
|
|
||||||
else
|
|
||||||
toSpeakList.append(fileIt.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Voice entries
|
|
||||||
m_logger->addItem(tr("Voicing entries..."),LOGINFO);
|
|
||||||
TTSStatus voiceStatus= voiceList(toSpeakList,voicedEntries);
|
|
||||||
if(voiceStatus == FatalError)
|
|
||||||
{
|
|
||||||
doAbort(toSpeakList);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encoding Entries
|
|
||||||
m_logger->addItem(tr("Encoding files..."),LOGINFO);
|
|
||||||
if(encodeList(voicedEntries,encodedEntries) == false)
|
|
||||||
{
|
|
||||||
doAbort(toSpeakList);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copying talk files
|
|
||||||
m_logger->addItem(tr("Copying Talkfile for Dirs..."),LOGINFO);
|
|
||||||
if(copyTalkDirFiles(dirList,&errStr) == false)
|
|
||||||
{
|
|
||||||
m_logger->addItem(errStr,LOGERROR);
|
|
||||||
doAbort(toSpeakList);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Copying file talk files
|
|
||||||
m_logger->addItem(tr("Copying Talkfile for Files..."),LOGINFO);
|
|
||||||
if(copyTalkFileFiles(fileList,&errStr) == false)
|
|
||||||
{
|
|
||||||
m_logger->addItem(errStr,LOGERROR);
|
|
||||||
doAbort(toSpeakList);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deleting left overs
|
|
||||||
if( !cleanup(toSpeakList))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_tts->stop();
|
|
||||||
m_enc->stop();
|
|
||||||
m_logger->addItem(tr("Finished creating Talk files"),LOGOK);
|
|
||||||
m_logger->setProgressMax(1);
|
|
||||||
m_logger->setProgressValue(1);
|
|
||||||
m_logger->setFinished();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \brief resets the internal progress counter, and sets the Progressbar in the Logger
|
|
||||||
//!
|
|
||||||
//! \param max The maximum to shich the Progressbar is set.
|
|
||||||
void TalkFileCreator::resetProgress(int max)
|
|
||||||
{
|
|
||||||
m_progress = 0;
|
|
||||||
m_logger->setProgressMax(max);
|
|
||||||
m_logger->setProgressValue(m_progress);
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \brief Strips everything after and including the last dot in a string. If there is no dot, nothing is changed
|
|
||||||
//!
|
|
||||||
//! \param filename The filename from which to strip the Extension
|
|
||||||
//! \returns the modified string
|
|
||||||
QString TalkFileCreator::stripExtension(QString filename)
|
|
||||||
{
|
|
||||||
if(filename.lastIndexOf(".") != -1)
|
|
||||||
return filename.left(filename.lastIndexOf("."));
|
|
||||||
else
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \brief Does needed Tasks when we need to abort. Cleans up Files. Stops the Logger, Stops TTS and Encoder
|
|
||||||
//!
|
|
||||||
//! \param cleanupList List of filenames to give to cleanup()
|
|
||||||
void TalkFileCreator::doAbort(QStringList cleanupList)
|
|
||||||
{
|
|
||||||
cleanup(cleanupList);
|
|
||||||
m_logger->setProgressMax(1);
|
|
||||||
m_logger->setProgressValue(0);
|
|
||||||
m_logger->setFinished();
|
|
||||||
m_tts->stop();
|
|
||||||
m_enc->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \brief Creates MultiMaps (paths -> File/dir names) of all Dirs and Files in a Folder.
|
|
||||||
//! Depending on settings, either Dirs or Files can be ignored.
|
|
||||||
//! Also recursion is controlled by settings
|
|
||||||
//!
|
|
||||||
//! \param startDir The dir where it beginns scanning
|
|
||||||
//! \param dirMap The MulitMap where the dirs are stored
|
|
||||||
//! \param filMap The MultiMap where Files are stored
|
|
||||||
//! \returns true on Success, false if User aborted.
|
|
||||||
bool TalkFileCreator::createDirAndFileMaps(QDir startDir,QMultiMap<QString,QString> *dirMap,QMultiMap<QString,QString> *fileMap)
|
|
||||||
{
|
|
||||||
// create Iterator
|
|
||||||
QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags;
|
|
||||||
if(m_recursive)
|
|
||||||
flags = QDirIterator::Subdirectories;
|
|
||||||
|
|
||||||
QDirIterator it(startDir,flags);
|
|
||||||
|
|
||||||
// read in Maps of paths - file/dirnames
|
|
||||||
while (it.hasNext())
|
|
||||||
{
|
|
||||||
it.next();
|
|
||||||
if(m_abort)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFileInfo fileInf = it.fileInfo();
|
|
||||||
|
|
||||||
// its a dir
|
|
||||||
if(fileInf.isDir())
|
|
||||||
{
|
|
||||||
QDir dir = fileInf.dir();
|
|
||||||
|
|
||||||
// insert into List
|
|
||||||
if(!dir.dirName().isEmpty() && m_talkFolders)
|
|
||||||
{
|
|
||||||
qDebug() << "Dir: " << dir.dirName() << " - " << dir.path();
|
|
||||||
dirMap->insert(dir.path(),dir.dirName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // its a File
|
|
||||||
{
|
|
||||||
// insert into List
|
|
||||||
if( !fileInf.fileName().isEmpty() && !fileInf.fileName().endsWith(".talk") && m_talkFiles)
|
|
||||||
{
|
|
||||||
qDebug() << "File: " << fileInf.fileName() << " - " << fileInf.path();
|
|
||||||
fileMap->insert(fileInf.path(),fileInf.fileName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \brief Voices a List of string to the temp dir. Progress is handled inside.
|
|
||||||
//!
|
|
||||||
//! \param toSpeak QStringList with the Entries to voice.
|
|
||||||
//! \param errString pointer to where the Error cause is written
|
|
||||||
//! \returns true on success, false on error or user abort
|
|
||||||
TTSStatus TalkFileCreator::voiceList(QStringList toSpeak,QStringList& voicedEntries)
|
|
||||||
{
|
|
||||||
resetProgress(toSpeak.size());
|
|
||||||
QStringList errors;
|
|
||||||
|
|
||||||
bool warnings = false;
|
|
||||||
for(int i=0; i < toSpeak.size(); i++)
|
|
||||||
{
|
|
||||||
if(m_abort)
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("Talk file creation aborted"), LOGERROR);
|
|
||||||
return FatalError;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString filename = QDir::tempPath()+ "/"+ toSpeak[i] + ".wav";
|
|
||||||
|
|
||||||
QString error;
|
|
||||||
TTSStatus status = m_tts->voice(toSpeak[i],filename, &error);
|
|
||||||
if(status == Warning)
|
|
||||||
{
|
|
||||||
warnings = true;
|
|
||||||
m_logger->addItem(tr("Voicing of %1 failed: %2").arg(toSpeak[i]).arg(error),
|
|
||||||
LOGWARNING);
|
|
||||||
}
|
|
||||||
else if (status == FatalError)
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("Voicing of %1 failed: %2").arg(toSpeak[i]).arg(error),
|
|
||||||
LOGERROR);
|
|
||||||
return FatalError;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
voicedEntries.append(toSpeak[i]);
|
|
||||||
m_logger->setProgressValue(++m_progress);
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
if(warnings)
|
|
||||||
return Warning;
|
|
||||||
else
|
|
||||||
return NoError;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! \brief Encodes a List of strings from/to the temp dir. Progress is handled inside.
|
|
||||||
//! It expects the inputfile in the temp dir with the name in the List appended with ".wav"
|
|
||||||
//!
|
|
||||||
//! \param toSpeak QStringList with the Entries to encode.
|
|
||||||
//! \param errString pointer to where the Error cause is written
|
|
||||||
//! \returns true on success, false on error or user abort
|
|
||||||
bool TalkFileCreator::encodeList(QStringList toEncode,QStringList& encodedEntries)
|
|
||||||
{
|
|
||||||
resetProgress(toEncode.size());
|
|
||||||
for(int i=0; i < toEncode.size(); i++)
|
|
||||||
{
|
|
||||||
if(m_abort)
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("Talk file creation aborted"), LOGERROR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString wavfilename = QDir::tempPath()+ "/"+ toEncode[i] + ".wav";
|
|
||||||
QString filename = QDir::tempPath()+ "/"+ toEncode[i] + ".talk";
|
|
||||||
|
|
||||||
if(!m_enc->encode(wavfilename,filename))
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("Encoding of %1 failed").arg(filename), LOGERROR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
encodedEntries.append(toEncode[i]);
|
|
||||||
m_logger->setProgressValue(++m_progress);
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \brief copys Talkfile for Dirs from the temp dir to the target. Progress and installlog is handled inside
|
|
||||||
//!
|
|
||||||
//! \param dirMap a MultiMap of Paths -> Dirnames
|
|
||||||
//! \param errString Pointer to a QString where the error cause is written.
|
|
||||||
//! \returns true on success, false on error or user abort
|
|
||||||
bool TalkFileCreator::copyTalkDirFiles(QMultiMap<QString,QString> dirMap,QString* errString)
|
|
||||||
{
|
|
||||||
resetProgress(dirMap.size());
|
|
||||||
|
|
||||||
QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
|
|
||||||
installlog.beginGroup("talkfiles");
|
|
||||||
|
|
||||||
QMapIterator<QString, QString> it(dirMap);
|
|
||||||
while (it.hasNext())
|
|
||||||
{
|
|
||||||
it.next();
|
|
||||||
if(m_abort)
|
|
||||||
{
|
|
||||||
*errString = tr("Talk file creation aborted");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString source = QDir::tempPath()+ "/"+ it.value() + ".talk";
|
|
||||||
|
|
||||||
if(!QFileInfo(source).exists())
|
|
||||||
continue; // this file was skipped in one of the previous steps
|
|
||||||
|
|
||||||
QString target = it.key() + "/" + "_dirname.talk";
|
|
||||||
|
|
||||||
// remove target if it exists, and if we should overwrite it
|
|
||||||
if(m_overwriteTalk && QFile::exists(target))
|
|
||||||
QFile::remove(target);
|
|
||||||
|
|
||||||
// copying
|
|
||||||
if(!QFile::copy(source,target))
|
|
||||||
{
|
|
||||||
*errString = tr("Copying of %1 to %2 failed").arg(source).arg(target);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add to installlog
|
|
||||||
QString now = QDate::currentDate().toString("yyyyMMdd");
|
|
||||||
installlog.setValue(target.remove(0,m_mountpoint.length()),now);
|
|
||||||
|
|
||||||
m_logger->setProgressValue(++m_progress);
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
installlog.endGroup();
|
|
||||||
installlog.sync();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \brief copys Talkfile for Files from the temp dir to the target. Progress and installlog is handled inside
|
|
||||||
//!
|
|
||||||
//! \param fileMap a MultiMap of Paths -> Filenames
|
|
||||||
//! \param errString Pointer to a QString where the error cause is written.
|
|
||||||
//! \returns true on success, false on error or user abort
|
|
||||||
bool TalkFileCreator::copyTalkFileFiles(QMultiMap<QString,QString> fileMap,QString* errString)
|
|
||||||
{
|
|
||||||
resetProgress(fileMap.size());
|
|
||||||
|
|
||||||
QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
|
|
||||||
installlog.beginGroup("talkfiles");
|
|
||||||
|
|
||||||
QMapIterator<QString, QString> it(fileMap);
|
|
||||||
while (it.hasNext())
|
|
||||||
{
|
|
||||||
it.next();
|
|
||||||
if(m_abort)
|
|
||||||
{
|
|
||||||
*errString = tr("Talk file creation aborted");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString source;
|
|
||||||
QString target = it.key() + "/" + it.value() + ".talk";
|
|
||||||
|
|
||||||
// correct source if we hav stripExtension enabled
|
|
||||||
if(m_stripExtensions)
|
|
||||||
source = QDir::tempPath()+ "/"+ stripExtension(it.value()) + ".talk";
|
|
||||||
else
|
|
||||||
source = QDir::tempPath()+ "/"+ it.value() + ".talk";
|
|
||||||
|
|
||||||
if(!QFileInfo(source).exists())
|
|
||||||
continue; // this file was skipped in one of the previous steps
|
|
||||||
|
|
||||||
// remove target if it exists, and if we should overwrite it
|
|
||||||
if(m_overwriteTalk && QFile::exists(target))
|
|
||||||
QFile::remove(target);
|
|
||||||
|
|
||||||
// copy file
|
|
||||||
qDebug() << "copying: " << source << " to " << target;
|
|
||||||
if(!QFile::copy(source,target))
|
|
||||||
{
|
|
||||||
*errString = tr("Copying of %1 to %2 failed").arg(source).arg(target);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add to Install log
|
|
||||||
QString now = QDate::currentDate().toString("yyyyMMdd");
|
|
||||||
installlog.setValue(target.remove(0,m_mountpoint.length()),now);
|
|
||||||
|
|
||||||
m_logger->setProgressValue(++m_progress);
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
installlog.endGroup();
|
|
||||||
installlog.sync();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//! \brief Cleans up Files potentially left in the temp dir
|
|
||||||
//!
|
|
||||||
//! \param list List of file to try to delete in the temp dir. Function appends ".wav" and ".talk" to the filenames
|
|
||||||
bool TalkFileCreator::cleanup(QStringList list)
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("Cleaning up.."),LOGINFO);
|
|
||||||
|
|
||||||
for(int i=0; i < list.size(); i++)
|
|
||||||
{
|
|
||||||
if(QFile::exists(QDir::tempPath()+ "/"+ list[i] + ".wav"))
|
|
||||||
QFile::remove(QDir::tempPath()+ "/"+ list[i] + ".wav");
|
|
||||||
if(QFile::exists(QDir::tempPath()+ "/"+ list[i] + ".talk"))
|
|
||||||
QFile::remove(QDir::tempPath()+ "/"+ list[i] + ".talk");
|
|
||||||
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \brief slot, which is connected to the abort of the Logger. Sets a flag, so Creating Talkfiles ends at the next possible position
|
|
||||||
//!
|
|
||||||
void TalkFileCreator::abort()
|
|
||||||
{
|
|
||||||
m_abort = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,301 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
* __________ __ ___.
|
|
||||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
||||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
||||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
||||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
||||||
* \/ \/ \/ \/ \/
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007 by Dominik Wenger
|
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
* All files in this archive are subject to the GNU General Public License.
|
|
||||||
* See the file COPYING in the source tree root for full license agreement.
|
|
||||||
*
|
|
||||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
||||||
* KIND, either express or implied.
|
|
||||||
*
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
#include "voicefile.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "rbsettings.h"
|
|
||||||
|
|
||||||
#define STATE_INVALID 0
|
|
||||||
#define STATE_PHRASE 1
|
|
||||||
#define STATE_VOICE 2
|
|
||||||
|
|
||||||
|
|
||||||
VoiceFileCreator::VoiceFileCreator(QObject* parent) :QObject(parent)
|
|
||||||
{
|
|
||||||
m_wavtrimThreshold=500;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoiceFileCreator::abort()
|
|
||||||
{
|
|
||||||
m_abort = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VoiceFileCreator::createVoiceFile(ProgressloggerInterface* logger)
|
|
||||||
{
|
|
||||||
m_abort = false;
|
|
||||||
m_logger = logger;
|
|
||||||
m_logger->addItem(tr("Starting Voicefile generation"),LOGINFO);
|
|
||||||
|
|
||||||
// test if tempdir exists
|
|
||||||
if(!QDir(QDir::tempPath()+"/rbvoice/").exists())
|
|
||||||
{
|
|
||||||
QDir(QDir::tempPath()).mkdir("rbvoice");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_path = QDir::tempPath() + "/rbvoice/";
|
|
||||||
|
|
||||||
// read rockbox-info.txt
|
|
||||||
RockboxInfo info(m_mountpoint);
|
|
||||||
if(!info.open())
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("could not find rockbox-info.txt"),LOGERROR);
|
|
||||||
m_logger->setFinished();
|
|
||||||
emit done(false);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString target = info.target();
|
|
||||||
QString features = info.features();
|
|
||||||
QString version = info.version();
|
|
||||||
version = version.left(version.indexOf("-")).remove(0,1);
|
|
||||||
|
|
||||||
//prepare download url
|
|
||||||
QUrl genlangUrl = RbSettings::value(RbSettings::GenlangUrl).toString()
|
|
||||||
+"?lang=" + m_lang + "&t=" + target + "&rev=" + version + "&f=" + features;
|
|
||||||
|
|
||||||
qDebug() << "downloading " << genlangUrl;
|
|
||||||
|
|
||||||
//download the correct genlang output
|
|
||||||
QTemporaryFile *downloadFile = new QTemporaryFile(this);
|
|
||||||
downloadFile->open();
|
|
||||||
filename = downloadFile->fileName();
|
|
||||||
downloadFile->close();
|
|
||||||
// get the real file.
|
|
||||||
getter = new HttpGet(this);
|
|
||||||
getter->setFile(downloadFile);
|
|
||||||
|
|
||||||
connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
|
|
||||||
connect(getter, SIGNAL(dataReadProgress(int, int)), this, SLOT(updateDataReadProgress(int, int)));
|
|
||||||
connect(m_logger, SIGNAL(aborted()), getter, SLOT(abort()));
|
|
||||||
|
|
||||||
getter->getFile(genlangUrl);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VoiceFileCreator::downloadDone(bool error)
|
|
||||||
{
|
|
||||||
qDebug() << "Voice creator::downloadDone, error:" << error;
|
|
||||||
|
|
||||||
// update progress bar
|
|
||||||
int max = m_logger->getProgressMax();
|
|
||||||
if(max == 0) {
|
|
||||||
max = 100;
|
|
||||||
m_logger->setProgressMax(max);
|
|
||||||
}
|
|
||||||
m_logger->setProgressValue(max);
|
|
||||||
if(getter->httpResponse() != 200 && !getter->isCached()) {
|
|
||||||
m_logger->addItem(tr("Download error: received HTTP error %1.").arg(getter->httpResponse()),LOGERROR);
|
|
||||||
m_logger->setFinished();
|
|
||||||
emit done(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(getter->isCached()) m_logger->addItem(tr("Cached file used."), LOGINFO);
|
|
||||||
if(error) {
|
|
||||||
m_logger->addItem(tr("Download error: %1").arg(getter->errorString()),LOGERROR);
|
|
||||||
m_logger->setFinished();
|
|
||||||
emit done(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else m_logger->addItem(tr("Download finished."),LOGOK);
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
|
|
||||||
|
|
||||||
m_logger->setProgressMax(0);
|
|
||||||
//open downloaded file
|
|
||||||
QFile genlang(filename);
|
|
||||||
if(!genlang.open(QIODevice::ReadOnly))
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("failed to open downloaded file"),LOGERROR);
|
|
||||||
m_logger->setFinished();
|
|
||||||
emit done(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//tts
|
|
||||||
m_tts = TTSBase::getTTS(this,RbSettings::value(RbSettings::Tts).toString());
|
|
||||||
|
|
||||||
QString errStr;
|
|
||||||
if(!m_tts->start(&errStr))
|
|
||||||
{
|
|
||||||
m_logger->addItem(errStr,LOGERROR);
|
|
||||||
m_logger->addItem(tr("Init of TTS engine failed"),LOGERROR);
|
|
||||||
m_logger->setFinished();
|
|
||||||
emit done(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encoder
|
|
||||||
m_enc = EncBase::getEncoder(this,RbSettings::value(RbSettings::CurEncoder).toString());
|
|
||||||
|
|
||||||
if(!m_enc->start())
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("Init of Encoder engine failed"),LOGERROR);
|
|
||||||
m_tts->stop();
|
|
||||||
m_logger->setFinished();
|
|
||||||
emit done(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
connect(m_logger,SIGNAL(aborted()),this,SLOT(abort()));
|
|
||||||
|
|
||||||
//read in downloaded file
|
|
||||||
QList<QPair<QString,QString> > voicepairs;
|
|
||||||
QTextStream in(&genlang);
|
|
||||||
in.setCodec("UTF-8");
|
|
||||||
QString id, voice;
|
|
||||||
bool idfound = false;
|
|
||||||
bool voicefound=false;
|
|
||||||
while (!in.atEnd())
|
|
||||||
{
|
|
||||||
QString line = in.readLine();
|
|
||||||
if(line.contains("id:")) //ID found
|
|
||||||
{
|
|
||||||
id = line.remove("id:").remove('"').trimmed();
|
|
||||||
idfound = true;
|
|
||||||
}
|
|
||||||
else if(line.contains("voice:")) // voice found
|
|
||||||
{
|
|
||||||
voice = line.remove("voice:").remove('"').trimmed();
|
|
||||||
voicefound=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(idfound && voicefound)
|
|
||||||
{
|
|
||||||
voicepairs.append(QPair<QString,QString>(id,voice));
|
|
||||||
idfound=false;
|
|
||||||
voicefound=false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
genlang.close();
|
|
||||||
|
|
||||||
// check for empty list
|
|
||||||
if(voicepairs.size() == 0)
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("The downloaded file was empty!"),LOGERROR);
|
|
||||||
m_logger->setFinished();
|
|
||||||
m_tts->stop();
|
|
||||||
emit done(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_logger->setProgressMax(voicepairs.size());
|
|
||||||
m_logger->setProgressValue(0);
|
|
||||||
|
|
||||||
// create voice clips
|
|
||||||
QStringList mp3files;
|
|
||||||
for(int i=0; i< voicepairs.size(); i++)
|
|
||||||
{
|
|
||||||
if(m_abort)
|
|
||||||
{
|
|
||||||
m_logger->addItem("aborted.",LOGERROR);
|
|
||||||
m_logger->setFinished();
|
|
||||||
m_tts->stop();
|
|
||||||
emit done(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_logger->setProgressValue(i);
|
|
||||||
|
|
||||||
QString wavname = m_path + "/" + voicepairs.at(i).first + ".wav";
|
|
||||||
QString toSpeak = voicepairs.at(i).second;
|
|
||||||
QString encodedname = m_path + "/" + voicepairs.at(i).first +".mp3";
|
|
||||||
|
|
||||||
// todo PAUSE
|
|
||||||
if(voicepairs.at(i).first == "VOICE_PAUSE")
|
|
||||||
{
|
|
||||||
QFile::copy(":/builtin/builtin/VOICE_PAUSE.wav",m_path + "/VOICE_PAUSE.wav");
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(toSpeak == "") continue;
|
|
||||||
|
|
||||||
m_logger->addItem(tr("creating ")+toSpeak,LOGINFO);
|
|
||||||
QCoreApplication::processEvents();
|
|
||||||
|
|
||||||
// TODO: add support for aborting the operation
|
|
||||||
QString errStr;
|
|
||||||
m_tts->voice(toSpeak,wavname, &errStr); // generate wav
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo strip
|
|
||||||
char buffer[255];
|
|
||||||
|
|
||||||
wavtrim((char*)qPrintable(wavname),m_wavtrimThreshold,buffer,255);
|
|
||||||
|
|
||||||
// encode wav
|
|
||||||
m_enc->encode(wavname,encodedname);
|
|
||||||
// remove the wav file
|
|
||||||
QFile::remove(wavname);
|
|
||||||
// remember the mp3 file for later removing
|
|
||||||
mp3files << encodedname;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//make voicefile
|
|
||||||
FILE* ids2 = fopen(filename.toUtf8(), "r");
|
|
||||||
if (ids2 == NULL)
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("Error opening downloaded file"),LOGERROR);
|
|
||||||
m_logger->setFinished();
|
|
||||||
emit done(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE* output = fopen(QString(m_mountpoint + "/.rockbox/langs/" + m_lang + ".voice").toUtf8(), "wb");
|
|
||||||
if (output == NULL)
|
|
||||||
{
|
|
||||||
m_logger->addItem(tr("Error opening output file"),LOGERROR);
|
|
||||||
emit done(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
voicefont(ids2,m_targetid,(char*)(const char*)m_path.toUtf8(), output);
|
|
||||||
|
|
||||||
//remove .mp3 files
|
|
||||||
for(int i=0;i< mp3files.size(); i++)
|
|
||||||
{
|
|
||||||
QFile::remove(mp3files.at(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add Voice file to the install log
|
|
||||||
QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0);
|
|
||||||
installlog.beginGroup("selfcreated Voice");
|
|
||||||
installlog.setValue("/.rockbox/langs/" + m_lang + ".voice",QDate::currentDate().toString("yyyyMMdd"));
|
|
||||||
installlog.endGroup();
|
|
||||||
installlog.sync();
|
|
||||||
|
|
||||||
m_logger->setProgressMax(100);
|
|
||||||
m_logger->setProgressValue(100);
|
|
||||||
m_logger->addItem(tr("successfully created."),LOGOK);
|
|
||||||
m_logger->setFinished();
|
|
||||||
|
|
||||||
emit done(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VoiceFileCreator::updateDataReadProgress(int read, int total)
|
|
||||||
{
|
|
||||||
m_logger->setProgressMax(total);
|
|
||||||
m_logger->setProgressValue(read);
|
|
||||||
//qDebug() << "progress:" << read << "/" << total;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue