From a9f50c35e684af8b6ca6061838b5ffa61f231c84 Mon Sep 17 00:00:00 2001 From: Dominik Wenger Date: Sat, 12 Jul 2008 17:04:49 +0000 Subject: rbutil: completly reworked Talkfile generation. Should be more stable and more maintainable. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18016 a1c6a512-1295-4272-9138-f99709370657 --- rbutil/rbutilqt/talkfile.cpp | 433 +++++++++++++++++++++++++++++++++---------- rbutil/rbutilqt/talkfile.h | 15 +- 2 files changed, 345 insertions(+), 103 deletions(-) diff --git a/rbutil/rbutilqt/talkfile.cpp b/rbutil/rbutilqt/talkfile.cpp index 4aa86fa21a..0c826e82aa 100644 --- a/rbutil/rbutilqt/talkfile.cpp +++ b/rbutil/rbutilqt/talkfile.cpp @@ -24,17 +24,25 @@ 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 fileList; + QMultiMap dirList; + QStringList toSpeakList; + QString errStr; + m_logger->addItem(tr("Starting Talk file generation"),LOGINFO); //tts m_tts = TTSBase::getTTS(settings->curTTS()); m_tts->setCfg(settings); - QString errStr; if(!m_tts->start(&errStr)) { m_logger->addItem(errStr.trimmed(),LOGERROR); @@ -59,141 +67,368 @@ bool TalkFileCreator::createTalkFiles(ProgressloggerInterface* logger) 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 dirIt(dirList); + while (dirIt.hasNext()) + { + dirIt.next(); + // insert only non dublicate dir entrys into list + if(!toSpeakList.contains(dirIt.value())) + { + qDebug() << "toSpeaklist dir:" << dirIt.value(); + toSpeakList.append(dirIt.value()); + } + } + QMapIterator fileIt(fileList); + while (fileIt.hasNext()) + { + fileIt.next(); + // insert only non- dublictae file entrys into list + if(!toSpeakList.contains(fileIt.value())) + { + if(m_stripExtensions) + toSpeakList.append(stripExtension(fileIt.value())); + else + toSpeakList.append(fileIt.value()); + } + } + + // Voice entrys + m_logger->addItem(tr("Voicing entrys..."),LOGINFO); + if(voiceList(toSpeakList,&errStr) == false) + { + m_logger->addItem(errStr,LOGERROR); + doAbort(toSpeakList); + return false; + } + + // Encoding Entrys + m_logger->addItem(tr("Encoding files..."),LOGINFO); + if(encodeList(toSpeakList,&errStr) == false) + { + m_logger->addItem(errStr,LOGERROR); + 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->abort(); + + 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->abort(); + 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 *dirMap,QMultiMap *fileMap) +{ + // create Iterator QDirIterator::IteratorFlags flags = QDirIterator::NoIteratorFlags; if(m_recursive) flags = QDirIterator::Subdirectories; - QDirIterator it(m_dir,flags); - QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0); - installlog.beginGroup("talkfiles"); - // iterate over all entrys + QDirIterator it(startDir,flags); + + // read in Maps of paths - file/dirnames while (it.hasNext()) { + it.next(); if(m_abort) { - m_logger->addItem(tr("Talk file creation aborted"),LOGERROR); - m_logger->abort(); - m_tts->stop(); - m_enc->stop(); return false; } - - QCoreApplication::processEvents(); + QFileInfo fileInf = it.fileInfo(); - QString toSpeak; - QString filename; - QString wavfilename; - QString filepath; - - QString path = fileInf.filePath(); - qDebug() << path; - - if( path.endsWith("..") || path.endsWith(".") || path.endsWith(".talk") ) - { - it.next(); - continue; - } - - //! if it is a dir - if(fileInf.isDir()) + + // its a dir + if(fileInf.isDir()) { - // skip entry if folder talking isnt enabled - if(m_talkFolders == false) + QDir dir = fileInf.dir(); + + // insert into List + if(!dir.dirName().isEmpty() && m_talkFolders) { - it.next(); - continue; + qDebug() << "Dir: " << dir.dirName() << " - " << dir.path(); + dirMap->insert(dir.path(),dir.dirName()); } - - toSpeak = fileInf.fileName(); - - filepath = fileInf.filePath() + "/"; - filename = "_dirname.talk"; - qDebug() << "toSpeak: " << toSpeak << "filename: " << filename << " path: " <insert(fileInf.path(),fileInf.fileName()); } - - // create toSpeak string - if(m_stripExtensions) - toSpeak = fileInf.baseName(); - else - toSpeak = fileInf.fileName(); - // create filename and path - filepath = fileInf.absolutePath(); - filename = fileInf.fileName() + ".talk"; - + } + QCoreApplication::processEvents(); + } + return true; +} + +//! \brief Voices a List of string to the temp dir. Progress is handled inside. +//! +//! \param toSpeak QStringList with the Entrys to voice. +//! \param errString pointer to where the Error cause is written +//! \returns true on success, false on error or user abort +bool TalkFileCreator::voiceList(QStringList toSpeak,QString* errString) +{ + resetProgress(toSpeak.size()); + + for(int i=0; i < toSpeak.size(); i++) + { + if(m_abort) + { + *errString = tr("Talk file creation aborted"); + return false; } - wavfilename = QDir::tempPath()+ "/"+ filename + ".wav"; + QString filename = QDir::tempPath()+ "/"+ toSpeak[i] + ".wav"; + + if(!m_tts->voice(toSpeak[i],filename)) + { + *errString =tr("Voicing of %s failed").arg(toSpeak[i]); + return false; + } + m_logger->setProgressValue(++m_progress); + QCoreApplication::processEvents(); + } + return true; +} - QFileInfo filenameInf(filepath+"/"+filename); - QFileInfo wavfilenameInf(wavfilename); - //! the actual generation of the .talk files - if(!filenameInf.exists() || m_overwriteTalk) +//! \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 Entrys 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,QString* errString) +{ + resetProgress(toEncode.size()); + for(int i=0; i < toEncode.size(); i++) + { + if(m_abort) { - if(!wavfilenameInf.exists() || m_overwriteWav) - { - m_logger->addItem(tr("Voicing of %1").arg(toSpeak),LOGINFO); - if(!m_tts->voice(toSpeak,wavfilename)) - { - m_logger->addItem(tr("Voicing of %s failed").arg(toSpeak),LOGERROR); - m_logger->abort(); - m_tts->stop(); - m_enc->stop(); - - return false; - } - QCoreApplication::processEvents(); - } - m_logger->addItem(tr("Encoding of %1").arg(toSpeak),LOGINFO); - if(!m_enc->encode(wavfilename,filepath+"/"+filename)) - { - m_logger->addItem(tr("Encoding of %1 failed").arg(wavfilename),LOGERROR); - m_logger->abort(); - m_tts->stop(); - m_enc->stop(); + *errString = tr("Talk file creation aborted"); + return false; + } + + QString wavfilename = QDir::tempPath()+ "/"+ toEncode[i] + ".wav"; + QString filename = QDir::tempPath()+ "/"+ toEncode[i] + ".talk"; + + if(!m_enc->encode(wavfilename,filename)) + { + *errString =tr("Encoding of %1 failed").arg(filename); + return false; + } + m_logger->setProgressValue(++m_progress); + QCoreApplication::processEvents(); + } + return true; +} - return false; - } - QCoreApplication::processEvents(); +//! \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 dirMap,QString* errString) +{ + resetProgress(dirMap.size()); + + QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0); + installlog.beginGroup("talkfiles"); + + QMapIterator 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"; + 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); - //! remove the intermedia wav file, if requested + // 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"); - if(m_removeWav) + 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 fileMap,QString* errString) +{ + resetProgress(fileMap.size()); + + QSettings installlog(m_mountpoint + "/.rockbox/rbutil.log", QSettings::IniFormat, 0); + installlog.beginGroup("talkfiles"); + + QMapIterator it(fileMap); + while (it.hasNext()) + { + it.next(); + if(m_abort) { - QFile wavfile(wavfilename); - wavfile.remove(); - installlog.remove(wavfilename); + *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 - installlog.setValue(wavfilename.remove(0,m_mountpoint.length()),now); + source = QDir::tempPath()+ "/"+ it.value() + ".talk"; - //! add the .talk file to the install log - installlog.setValue(QString(filepath+"/"+filename).remove(0,m_mountpoint.length()),now); - it.next(); + // 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(); - 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->abort(); + installlog.sync(); + return true; +} - 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; diff --git a/rbutil/rbutilqt/talkfile.h b/rbutil/rbutilqt/talkfile.h index f4e9b4c88e..d869c32880 100644 --- a/rbutil/rbutilqt/talkfile.h +++ b/rbutil/rbutilqt/talkfile.h @@ -44,8 +44,6 @@ public: void setMountPoint(QString mountpoint) {m_mountpoint =mountpoint; } void setOverwriteTalk(bool ov) {m_overwriteTalk = ov;} - void setOverwriteWav(bool ov) {m_overwriteWav = ov;} - void setRemoveWav(bool ov) {m_removeWav = ov;} void setRecursive(bool ov) {m_recursive = ov;} void setStripExtensions(bool ov) {m_stripExtensions = ov;} void setTalkFolders(bool ov) {m_talkFolders = ov;} @@ -55,16 +53,25 @@ private slots: void abort(); private: + bool cleanup(QStringList list); + QString stripExtension(QString filename); + void doAbort(QStringList cleanupList); + void resetProgress(int max); + bool createDirAndFileMaps(QDir startDir,QMultiMap *dirMap,QMultiMap *fileMap); + bool voiceList(QStringList toSpeak,QString* errString); + bool encodeList(QStringList toEncode,QString* errString); + bool copyTalkDirFiles(QMultiMap dirMap,QString* errString); + bool copyTalkFileFiles(QMultiMap fileMap,QString* errString); + TTSBase* m_tts; EncBase* m_enc; RbSettings* settings; QDir m_dir; QString m_mountpoint; + int m_progress; bool m_overwriteTalk; - bool m_overwriteWav; - bool m_removeWav; bool m_recursive; bool m_stripExtensions; bool m_talkFolders; -- cgit v1.2.3