Index: rbutil/rbutilqt/ttsgui.cpp
===================================================================
--- rbutil/rbutilqt/ttsgui.cpp (revision 20206)
+++ rbutil/rbutilqt/ttsgui.cpp (working copy)
@@ -16,13 +16,13 @@
* KIND, either express or implied.
*
****************************************************************************/
-
+
#include "ttsgui.h"
#include "rbsettings.h"
#include "tts.h"
#include "browsedirtree.h"
-
+
TTSSapiGui::TTSSapiGui(TTSSapi* sapi,QDialog* parent) : QDialog(parent)
{
m_sapi= sapi;
@@ -31,46 +31,46 @@
connect(ui.reset,SIGNAL(clicked()),this,SLOT(reset()));
connect(ui.languagecombo,SIGNAL(currentIndexChanged(QString)),this,SLOT(updateVoices(QString)));
connect(ui.usesapi4,SIGNAL(stateChanged(int)),this,SLOT(useSapi4Changed(int)));
-}
+}
void TTSSapiGui::showCfg()
{
// try to get config from settings
- ui.ttsoptions->setText(settings->ttsOptions("sapi"));
+ ui.ttsoptions->setText(settings->ttsOptions("sapi"));
QString selLang = settings->ttsLang("sapi");
- QString selVoice = settings->ttsVoice("sapi");
+ QString selVoice = settings->ttsVoice("sapi");
ui.speed->setValue(settings->ttsSpeed("sapi"));
if(settings->ttsUseSapi4())
ui.usesapi4->setCheckState(Qt::Checked);
else
ui.usesapi4->setCheckState(Qt::Unchecked);
-
+
// fill in language combobox
QStringList languages = settings->allLanguages();
-
+
languages.sort();
ui.languagecombo->clear();
ui.languagecombo->addItems(languages);
-
+
// set saved lang
ui.languagecombo->setCurrentIndex(ui.languagecombo->findText(selLang));
- // fill in voice combobox
+ // fill in voice combobox
updateVoices(selLang);
-
+
// set saved lang
- ui.voicecombo->setCurrentIndex(ui.voicecombo->findText(selVoice));
-
+ ui.voicecombo->setCurrentIndex(ui.voicecombo->findText(selVoice));
+
//show dialog
this->exec();
-
+
}
void TTSSapiGui::reset()
{
- ui.ttsoptions->setText("");
- ui.languagecombo->setCurrentIndex(ui.languagecombo->findText("english"));
+ ui.ttsoptions->setText("");
+ ui.languagecombo->setCurrentIndex(ui.languagecombo->findText("english"));
}
@@ -101,7 +101,7 @@
{
QStringList Voices = m_sapi->getVoiceList(language);
ui.voicecombo->clear();
- ui.voicecombo->addItems(Voices);
+ ui.voicecombo->addItems(Voices);
}
@@ -114,7 +114,7 @@
// sync settings
settings->sync();
updateVoices(ui.languagecombo->currentText());
-
+
}
TTSExesGui::TTSExesGui(QDialog* parent) : QDialog(parent)
@@ -129,7 +129,7 @@
void TTSExesGui::reset()
{
ui.ttspath->setText("");
- ui.ttsoptions->setText("");
+ ui.ttsoptions->setText("");
}
void TTSExesGui::showCfg(QString name)
@@ -137,12 +137,12 @@
m_name = name;
// try to get config from settings
QString exepath =settings->ttsPath(m_name);
- ui.ttsoptions->setText(settings->ttsOptions(m_name));
+ ui.ttsoptions->setText(settings->ttsOptions(m_name));
ui.ttspath->setText(exepath);
-
+
//show dialog
this->exec();
-
+
}
void TTSExesGui::accept(void)
@@ -152,7 +152,7 @@
settings->setTTSOptions(m_name,ui.ttsoptions->text());
// sync settings
settings->sync();
-
+
this->done(0);
}
@@ -181,3 +181,55 @@
}
}
+
+TTSFestivalGui::TTSFestivalGui(TTSFestival* api, QDialog* parent) :
+ QDialog(parent), festival(api)
+{
+ ui.setupUi(this);
+ this->hide();
+
+ connect(ui.refreshButton, SIGNAL(clicked()), this, SLOT(updateVoices()));
+}
+
+void TTSFestivalGui::showCfg()
+{
+ // will populate the voices if the paths are correct,
+ // otherwise, it will require the user to press Refresh
+ updateVoices();
+
+ // try to get config from settings
+ QStringList paths = settings->ttsPath("festival").split(":");
+ if(paths.size() == 2)
+ {
+ ui.serverPath->setText(paths[0]);
+ ui.clientPath->setText(paths[1]);
+ }
+ ui.voicesBox->setCurrentIndex(ui.voicesBox->findText(settings->ttsVoice("festival")));
+
+ //show dialog
+ this->exec();
+
+}
+
+void TTSFestivalGui::accept(void)
+{
+ //save settings in user config
+ settings->setTTSPath("festival", QString("%1:%2").arg(ui.serverPath->text().trimmed()).arg(ui.clientPath->text().trimmed()));
+ settings->setTTSVoice("festival", ui.voicesBox->currentText());
+
+ settings->sync();
+
+ this->done(0);
+}
+
+void TTSFestivalGui::reject(void)
+{
+ this->done(0);
+}
+
+void TTSFestivalGui::updateVoices()
+{
+ ui.voicesBox->clear();
+ ui.voicesBox->addItems(festival->getVoiceList());
+ ui.voicesBox->setCurrentIndex(ui.voicesBox->findText(settings->ttsVoice("festival")));
+}
Index: rbutil/rbutilqt/ttsfestivalcfgform.ui
===================================================================
--- rbutil/rbutilqt/ttsfestivalcfgform.ui (revision 0)
+++ rbutil/rbutilqt/ttsfestivalcfgform.ui (revision 0)
@@ -0,0 +1,300 @@
+
+ TTSFestivalCfgFrm
+
+
+
+ 0
+ 0
+ 340
+ 314
+
+
+
+ Configuration
+
+
+ -
+
+
+
+ 1
+ 0
+
+
+
+ Executables
+
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ QLayout::SetMinimumSize
+
+
+ 6
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Path to Festival server
+
+
+
+ -
+
+
+
+ 1
+ 0
+
+
+
+
+ 215
+ 0
+
+
+
+
+ -
+
+
+ Browse
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Path to Festival client
+
+
+
+ -
+
+
+
+ 1
+ 0
+
+
+
+
+ 215
+ 0
+
+
+
+
+ -
+
+
+ Browse
+
+
+
+
+
+
+ label
+ serverPath
+ serverButton
+ label_2
+ layoutWidget
+ groupBox2
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 153
+ 43
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+ false
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 70
+ 20
+
+
+
+
+ -
+
+
+
+ 1
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Server voice
+
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Select a voice
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ &Refresh
+
+
+
+ :/icons/view-refresh.png:/icons/view-refresh.png
+
+
+
+ -
+
+
+
+ 1
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+ buttonBox
+ execsBox
+ verticalSpacer
+ horizontalSpacer
+ verticalSpacer
+ groupBox2
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ TTSFestivalCfgFrm
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ TTSFestivalCfgFrm
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
Index: rbutil/rbutilqt/tts.cpp
===================================================================
--- rbutil/rbutilqt/tts.cpp (revision 20206)
+++ rbutil/rbutilqt/tts.cpp (working copy)
@@ -33,7 +33,7 @@
#if defined(Q_OS_WIN)
ttsList["sapi"] = "Sapi TTS Engine";
#endif
-
+ ttsList["festival"] = "Festival TTS Engine";
}
// function to get a specific encoder
@@ -47,11 +47,17 @@
if(ttsName == "sapi")
{
tts = new TTSSapi();
- ttsCache[ttsName] = tts;
+ ttsCache[ttsName] = tts;
return tts;
}
- else
+ else if (ttsName == "festival")
{
+ tts = new TTSFestival();
+ ttsCache[ttsName] = tts;
+ return tts;
+ }
+ else
+ {
tts = new TTSExes(ttsName);
ttsCache[ttsName] = tts;
return tts;
@@ -90,30 +96,30 @@
TTSExes::TTSExes(QString name) : TTSBase()
{
m_name = name;
-
+
m_TemplateMap["espeak"] = "\"%exe\" %options -w \"%wavfile\" \"%text\"";
- m_TemplateMap["flite"] = "\"%exe\" %options -o \"%wavfile\" \"%text\"";
+ m_TemplateMap["flite"] = "\"%exe\" %options -o \"%wavfile\" -t \"%text\"";
m_TemplateMap["swift"] = "\"%exe\" %options -o \"%wavfile\" \"%text\"";
-
+
}
void TTSExes::setCfg(RbSettings* sett)
{
// call function of base class
TTSBase::setCfg(sett);
-
+
// if the config isnt OK, try to autodetect
if(!configOk())
{
QString exepath;
- //try autodetect tts
+ //try autodetect tts
#if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_OPENBSD)
QStringList path = QString(getenv("PATH")).split(":", QString::SkipEmptyParts);
#elif defined(Q_OS_WIN)
QStringList path = QString(getenv("PATH")).split(";", QString::SkipEmptyParts);
#endif
qDebug() << path;
- for(int i = 0; i < path.size(); i++)
+ for(int i = 0; i < path.size(); i++)
{
QString executable = QDir::fromNativeSeparators(path.at(i)) + "/" + m_name;
#if defined(Q_OS_WIN)
@@ -131,14 +137,14 @@
settings->setTTSPath(m_name,exepath);
settings->sync();
}
-
+
}
bool TTSExes::start(QString *errStr)
{
m_TTSexec = settings->ttsPath(m_name);
m_TTSOpts = settings->ttsOptions(m_name);
-
+
m_TTSTemplate = m_TemplateMap.value(m_name);
QFileInfo tts(m_TTSexec);
@@ -153,8 +159,10 @@
}
}
-bool TTSExes::voice(QString text,QString wavfile)
+TTSStatus TTSExes::voice(QString text,QString wavfile, QString *errStr, bool ignoreNonAscii)
{
+ TTSBase::voice(text, wavfile, errStr, ignoreNonAscii);
+
QString execstring = m_TTSTemplate;
execstring.replace("%exe",m_TTSexec);
@@ -163,7 +171,7 @@
execstring.replace("%text",text);
//qDebug() << "voicing" << execstring;
QProcess::execute(execstring);
- return true;
+ return NoError;
}
@@ -181,10 +189,10 @@
bool TTSExes::configOk()
{
QString path = settings->ttsPath(m_name);
-
+
if (QFileInfo(path).exists())
return true;
-
+
return false;
}
@@ -200,24 +208,24 @@
bool TTSSapi::start(QString *errStr)
-{
+{
m_TTSOpts = settings->ttsOptions("sapi");
m_TTSLanguage =settings->ttsLang("sapi");
m_TTSVoice=settings->ttsVoice("sapi");
m_TTSSpeed=QString("%1").arg(settings->ttsSpeed("sapi"));
m_sapi4 = settings->ttsUseSapi4();
-
+
QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
QFile::copy(":/builtin/sapi_voice.vbs",QDir::tempPath() + "/sapi_voice.vbs");
m_TTSexec = QDir::tempPath() +"/sapi_voice.vbs";
-
+
QFileInfo tts(m_TTSexec);
if(!tts.exists())
{
*errStr = tr("Could not copy the Sapi-script");
return false;
- }
+ }
// create the voice process
QString execstring = m_TTSTemplate;
execstring.replace("%exe",m_TTSexec);
@@ -225,31 +233,31 @@
execstring.replace("%lang",m_TTSLanguage);
execstring.replace("%voice",m_TTSVoice);
execstring.replace("%speed",m_TTSSpeed);
-
+
if(m_sapi4)
execstring.append(" /sapi4 ");
-
- qDebug() << "init" << execstring;
+
+ qDebug() << "init" << execstring;
voicescript = new QProcess(NULL);
//connect(voicescript,SIGNAL(readyReadStandardError()),this,SLOT(error()));
-
+
voicescript->start(execstring);
if(!voicescript->waitForStarted())
{
*errStr = tr("Could not start the Sapi-script");
return false;
}
-
- if(!voicescript->waitForReadyRead(300))
+
+ if(!voicescript->waitForReadyRead(300))
{
*errStr = voicescript->readAllStandardError();
if(*errStr != "")
- return false;
+ return false;
}
-
+
voicestream = new QTextStream(voicescript);
voicestream->setCodec("UTF16-LE");
-
+
return true;
}
@@ -257,31 +265,31 @@
QStringList TTSSapi::getVoiceList(QString language)
{
QStringList result;
-
+
QFile::copy(":/builtin/sapi_voice.vbs",QDir::tempPath() + "/sapi_voice.vbs");
m_TTSexec = QDir::tempPath() +"/sapi_voice.vbs";
-
+
QFileInfo tts(m_TTSexec);
if(!tts.exists())
return result;
-
+
// create the voice process
QString execstring = "cscript //nologo \"%exe\" /language:%lang /listvoices";
execstring.replace("%exe",m_TTSexec);
execstring.replace("%lang",language);
-
+
if(settings->ttsUseSapi4())
execstring.append(" /sapi4 ");
-
- qDebug() << "init" << execstring;
+
+ qDebug() << "init" << execstring;
voicescript = new QProcess(NULL);
voicescript->start(execstring);
- qDebug() << "wait for started";
+ qDebug() << "wait for started";
if(!voicescript->waitForStarted())
return result;
voicescript->closeWriteChannel();
voicescript->waitForReadyRead();
-
+
QString dataRaw = voicescript->readAllStandardError().data();
result = dataRaw.split(",",QString::SkipEmptyParts);
result.sort();
@@ -290,40 +298,41 @@
{
result[i] = result.at(i).simplified();
}
-
-
+
+
delete voicescript;
- QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",QFile::ReadOwner |QFile::WriteOwner|QFile::ExeOwner
+ QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",QFile::ReadOwner |QFile::WriteOwner|QFile::ExeOwner
|QFile::ReadUser| QFile::WriteUser| QFile::ExeUser
|QFile::ReadGroup |QFile::WriteGroup |QFile::ExeGroup
|QFile::ReadOther |QFile::WriteOther |QFile::ExeOther );
QFile::remove(QDir::tempPath() +"/sapi_voice.vbs");
-
+
return result;
}
-bool TTSSapi::voice(QString text,QString wavfile)
+TTSStatus TTSSapi::voice(QString text,QString wavfile, QString *errStr, bool ignoreNonAscii)
{
+ TTSBase::voice(text, wavfile, errStr, ignoreNonAscii);
QString query = "SPEAK\t"+wavfile+"\t"+text+"\r\n";
qDebug() << "voicing" << query;
*voicestream << query;
*voicestream << "SYNC\tbla\r\n";
voicestream->flush();
voicescript->waitForReadyRead();
- return true;
+ return NoError;
}
bool TTSSapi::stop()
-{
-
+{
+
*voicestream << "QUIT\r\n";
voicestream->flush();
voicescript->waitForFinished();
delete voicestream;
delete voicescript;
- QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",QFile::ReadOwner |QFile::WriteOwner|QFile::ExeOwner
+ QFile::setPermissions(QDir::tempPath() +"/sapi_voice.vbs",QFile::ReadOwner |QFile::WriteOwner|QFile::ExeOwner
|QFile::ReadUser| QFile::WriteUser| QFile::ExeUser
|QFile::ReadGroup |QFile::WriteGroup |QFile::ExeGroup
|QFile::ReadOther |QFile::WriteOther |QFile::ExeOther );
@@ -351,3 +360,236 @@
}
+/**********************************************************************
+ * TSSFestival - client-server wrapper
+ **********************************************************************/
+TTSFestival::TTSFestival()
+{
+}
+
+void TTSFestival::startServer()
+{
+ if(!configOk())
+ return;
+
+ QStringList paths = settings->ttsPath("festival").split(":");
+
+ serverProcess.start(QString("%1 --server").arg(paths[0]));
+ serverProcess.waitForStarted();
+ serverProcess.waitForReadyRead();
+
+ QString response(serverProcess.readAll());
+ if (!response.isEmpty())
+ qDebug() << "Festival is up and running";
+ else
+ qDebug() << "Festival failed to start";
+
+ // at this point the server has entered the Scheme engine
+ // but we still cannot send it commands
+ // serverProcess.waitForReadyRead(2000);
+}
+
+void TTSFestival::ensureServerRunning()
+{
+ if(serverProcess.state() != QProcess::Running)
+ startServer();
+}
+
+bool TTSFestival::start(QString* errStr)
+{
+ ensureServerRunning();
+ if (!settings->ttsVoice("festival").isEmpty())
+ {
+ QTcpSocket setVoiceSocket;
+ setVoiceSocket.connectToHost("localhost", 1314);
+ setVoiceSocket.waitForConnected();
+ setVoiceSocket.write(QString("(voice_%1)\n").arg(settings->ttsVoice("festival")).toAscii());
+ setVoiceSocket.waitForBytesWritten();
+ setVoiceSocket.waitForReadyRead();
+ qDebug() << setVoiceSocket.readAll();
+ setVoiceSocket.disconnectFromHost();
+ }
+
+ return true;
+}
+
+bool TTSFestival::stop()
+{
+ serverProcess.terminate();
+ serverProcess.kill();
+
+ return true;
+}
+
+TTSStatus TTSFestival::voice(QString text, QString wavfile, QString* errStr, bool ignoreNonAscii)
+{
+ TTSBase::voice(text, wavfile, errStr, ignoreNonAscii);
+ qDebug() << text << "->" << wavfile;
+ QStringList paths = settings->ttsPath("festival").split(":");
+ QString cmd = QString("%1 --server localhost --otype riff --ttw --withlisp --output \"%2\" - ").arg(paths[1]).arg(wavfile);
+ qDebug() << cmd;
+
+ QProcess clientProcess;
+ clientProcess.start(cmd);
+ clientProcess.write(QString("%1.\n").arg(text).toAscii());
+ clientProcess.waitForBytesWritten();
+ clientProcess.closeWriteChannel();
+ clientProcess.waitForReadyRead();
+ QString response = clientProcess.readAll();
+ response = response.trimmed();
+ if(response.contains("nist"))
+ {
+ *errStr = tr("engine could not voice string");
+ return FatalError;
+ }
+ clientProcess.closeReadChannel(QProcess::StandardError);
+ clientProcess.closeReadChannel(QProcess::StandardOutput);
+ clientProcess.terminate();
+ clientProcess.kill();
+
+ QFileInfo info(wavfile);
+ do
+ {
+ info.refresh();
+ }
+ while(!info.exists());
+
+ return NoError;
+}
+
+bool TTSFestival::configOk()
+{
+ QStringList paths = settings->ttsPath("festival").split(":");
+ if(paths.size() != 2)
+ return false;
+ bool ret = QFileInfo(paths[0]).isExecutable() &&
+ QFileInfo(paths[1]).isExecutable();
+ if(settings->ttsVoice("festival").size() > 0 && voices.size() > 0)
+ ret = ret && voices.indexOf(settings->ttsVoice("festival")) != -1;
+ return ret;
+}
+
+void TTSFestival::showCfg()
+{
+#ifndef CONSOLE
+ TTSFestivalGui gui(this);
+#endif
+ gui.setCfg(settings);
+ gui.showCfg();
+}
+
+
+QStringList TTSFestival::getVoiceList()
+{
+ if(!configOk())
+ return QStringList();
+
+ if(voices.size() > 0)
+ {
+ qDebug() << "Using voice cache";
+ return voices;
+ }
+ ensureServerRunning();
+
+ QTcpSocket socket;
+ QStringList responseLines;
+ QString response;
+ size_t retry = 0;
+ do
+ {
+ socket.connectToHost("localhost", 1314);
+ socket.waitForConnected();
+
+ if (socket.state() != QAbstractSocket::ConnectedState)
+ {
+ ensureServerRunning();
+ qDebug() << "Error: " << socket.errorString();
+ continue;
+ }
+ socket.write(QString("(voice.list)\n\n").toAscii());
+ socket.waitForBytesWritten();
+ socket.waitForReadyRead();
+
+ response = socket.readAll();
+ response = response.trimmed();
+ responseLines = response.split('\n');
+ qDebug() << responseLines;
+
+ socket.disconnectFromHost();
+
+ retry += 1;
+ if (retry >= 10)
+ {
+ qDebug() << "Could not get voices list";
+ return QStringList();
+ }
+ }while(responseLines.size() < 2);
+
+ if (!responseLines[0].startsWith("LP"))
+ return QStringList();
+
+ // responseLine should be (, )
+ voices = responseLines[1].mid(1, responseLines[1].size()-2).split(' ');
+
+ voices.sort();
+ if (voices.size() == 1 && voices[0].size() == 0)
+ voices.removeAt(0);
+ if (voices.size() > 0)
+ qDebug() << "Voices: " << voices;
+ else
+ qDebug() << "No voices.";
+ return voices;
+}
+
+
+void TTSFestival::setCfg(RbSettings* sett)
+{
+ // call function of base class
+ TTSBase::setCfg(sett);
+
+ // if the config isnt OK, try to autodetect
+ if(!configOk())
+ {
+ QString exepath;
+ //try autodetect tts
+#if defined(Q_OS_LINUX) || defined(Q_OS_MACX) || defined(Q_OS_OPENBSD)
+ QStringList path = QString(getenv("PATH")).split(":", QString::SkipEmptyParts);
+#elif defined(Q_OS_WIN)
+ QStringList path = QString(getenv("PATH")).split(";", QString::SkipEmptyParts);
+#endif
+ qDebug() << path;
+ for(int i = 0; i < path.size(); i++)
+ {
+ QString server = QDir::fromNativeSeparators(path.at(i)) + "/" + "festival";
+ QString client = QDir::fromNativeSeparators(path.at(i)) + "/" + "festival_client";
+#if defined(Q_OS_WIN)
+ server += ".exe";
+ client += ".exe";
+ QStringList ex = server.split("\"", QString::SkipEmptyParts);
+ server = ex.join("");
+ ex = client.split("\"", QString::SkipEmptyParts);
+ client = ex.join("");
+#endif
+ qDebug() << server << client;
+ if(QFileInfo(server).isExecutable() && QFileInfo(client).isExecutable())
+ {
+ exepath= QDir::toNativeSeparators(server) + ":" + QDir::toNativeSeparators(client);
+ break;
+ }
+ }
+ settings->setTTSPath("festival",exepath);
+ settings->sync();
+ }
+
+}
+
+bool TTSBase::isASCII(const QString str)
+{
+ QByteArray data = str.toUtf8();
+ for(int i=0; i 127
+ return false;
+ }
+ return true;
+}
Index: rbutil/rbutilqt/ttsexescfgfrm.ui
===================================================================
--- rbutil/rbutilqt/ttsexescfgfrm.ui (revision 20206)
+++ rbutil/rbutilqt/ttsexescfgfrm.ui (working copy)
@@ -5,8 +5,8 @@
0
0
- 463
- 214
+ 389
+ 206
@@ -22,7 +22,7 @@
-
-
+
0
255
@@ -61,7 +61,7 @@
Qt::Vertical
-
+
20
40
@@ -83,7 +83,7 @@
Qt::Horizontal
-
+
40
20
@@ -97,7 +97,8 @@
&Ok
- :/icons/go-next.png
+
+ :/icons/go-next.png:/icons/go-next.png
@@ -107,7 +108,8 @@
&Cancel
- :/icons/process-stop.png
+
+ :/icons/process-stop.png:/icons/process-stop.png
Index: rbutil/rbutilqt/rbutilqt.pro
===================================================================
--- rbutil/rbutilqt/rbutilqt.pro (revision 20206)
+++ rbutil/rbutilqt/rbutilqt.pro (working copy)
@@ -1,12 +1,13 @@
-unix:!mac {
+unix:!mac {
CCACHE = $$system(which ccache)
- !isEmpty(CCACHE) {
+ !isEmpty(CCACHE) {
message("using ccache")
- QMAKE_CXX = ccache g++
- QMAKE_CC = ccache gcc
+ QMAKE_CXX = ccache \
+ g++
+ QMAKE_CC = ccache \
+ gcc
}
}
-
OBJECTS_DIR = build/o
UI_DIR = build/ui
MOC_DIR = build/moc
@@ -14,237 +15,249 @@
# check version of Qt installation
VER = $$find(QT_VERSION, ^4\.[3-9]+.*)
-isEmpty(VER) {
+isEmpty(VER) {
!isEmpty(QT_VERSION) error("Qt found:" $$[QT_VERSION])
error("Qt >= 4.3 required!")
}
message("Qt version used:" $$VER)
# add a custom rule for pre-building librbspeex
-!mac {
-rbspeex.commands = @$(MAKE) -C ../../tools/rbspeex librbspeex.a
-}
-mac {
-rbspeex.commands = @$(MAKE) -C ../../tools/rbspeex librbspeex-universal
-}
+!mac:rbspeex.commands = @$(MAKE) \
+ -C \
+ ../../tools/rbspeex \
+ librbspeex.a
+mac:rbspeex.commands = @$(MAKE) \
+ -C \
+ ../../tools/rbspeex \
+ librbspeex-universal
QMAKE_EXTRA_TARGETS += rbspeex
PRE_TARGETDEPS += rbspeex
# rule for creating ctags file
-tags.commands = ctags -R --c++-kinds=+p --fields=+iaS --extra=+q $(SOURCES)
+tags.commands = ctags \
+ -R \
+ --c++-kinds=+p \
+ --fields=+iaS \
+ --extra=+q \
+ $(SOURCES)
tags.depends = $(SOURCES)
QMAKE_EXTRA_TARGETS += tags
# add a custom rule for making the translations
-lrelease.commands = $$[QT_INSTALL_BINS]/lrelease -silent rbutilqt.pro
+lrelease.commands = $$[QT_INSTALL_BINS]/lrelease \
+ -silent \
+ rbutilqt.pro
QMAKE_EXTRA_TARGETS += lrelease
-!dbg {
- PRE_TARGETDEPS += lrelease
-}
-
-
+!dbg:PRE_TARGETDEPS += lrelease
SOURCES += rbutilqt.cpp \
- main.cpp \
- install.cpp \
- base/httpget.cpp \
- configure.cpp \
- zip/zip.cpp \
- zip/unzip.cpp \
- installzip.cpp \
- progressloggergui.cpp \
- installtalkwindow.cpp \
- talkfile.cpp \
- base/autodetection.cpp \
- ../ipodpatcher/ipodpatcher.c \
- ../sansapatcher/sansapatcher.c \
- browsedirtree.cpp \
- installthemes.cpp \
- base/uninstall.cpp \
- uninstallwindow.cpp \
- base/utils.cpp \
- preview.cpp \
- encoders.cpp \
- encodersgui.cpp \
- tts.cpp \
- ttsgui.cpp \
- ../../tools/wavtrim.c \
- ../../tools/voicefont.c \
- voicefile.cpp \
- createvoicewindow.cpp \
- rbsettings.cpp \
- base/rbunzip.cpp \
- base/rbzip.cpp \
- base/detect.cpp \
- sysinfo.cpp \
- base/bootloaderinstallbase.cpp \
- base/bootloaderinstallmi4.cpp \
- base/bootloaderinstallhex.cpp \
- base/bootloaderinstallipod.cpp \
- base/bootloaderinstallsansa.cpp \
- base/bootloaderinstallfile.cpp \
- ../../tools/mkboot.c \
- ../../tools/iriver.c
-
+ main.cpp \
+ install.cpp \
+ base/httpget.cpp \
+ configure.cpp \
+ zip/zip.cpp \
+ zip/unzip.cpp \
+ installzip.cpp \
+ progressloggergui.cpp \
+ installtalkwindow.cpp \
+ talkfile.cpp \
+ base/autodetection.cpp \
+ ../ipodpatcher/ipodpatcher.c \
+ ../sansapatcher/sansapatcher.c \
+ browsedirtree.cpp \
+ installthemes.cpp \
+ base/uninstall.cpp \
+ uninstallwindow.cpp \
+ base/utils.cpp \
+ preview.cpp \
+ encoders.cpp \
+ encodersgui.cpp \
+ tts.cpp \
+ ttsgui.cpp \
+ ../../tools/wavtrim.c \
+ ../../tools/voicefont.c \
+ voicefile.cpp \
+ createvoicewindow.cpp \
+ rbsettings.cpp \
+ base/rbunzip.cpp \
+ base/rbzip.cpp \
+ base/detect.cpp \
+ sysinfo.cpp \
+ base/bootloaderinstallbase.cpp \
+ base/bootloaderinstallmi4.cpp \
+ base/bootloaderinstallhex.cpp \
+ base/bootloaderinstallipod.cpp \
+ base/bootloaderinstallsansa.cpp \
+ base/bootloaderinstallfile.cpp \
+ ../../tools/mkboot.c \
+ ../../tools/iriver.c
HEADERS += rbutilqt.h \
- install.h \
- base/httpget.h \
- configure.h \
- zip/zip.h \
- zip/unzip.h \
- zip/zipentry_p.h \
- zip/unzip_p.h \
- zip/zip_p.h \
- version.h \
- installzip.h \
- installtalkwindow.h \
- talkfile.h \
- base/autodetection.h \
- progressloggerinterface.h \
- progressloggergui.h \
- ../ipodpatcher/ipodpatcher.h \
- ../ipodpatcher/ipodio.h \
- ../ipodpatcher/parttypes.h \
- ../sansapatcher/sansapatcher.h \
- ../sansapatcher/sansaio.h \
- irivertools/h100sums.h \
- irivertools/h120sums.h \
- irivertools/h300sums.h \
- browsedirtree.h \
- installthemes.h \
- base/uninstall.h \
- uninstallwindow.h \
- base/utils.h \
- preview.h \
- encoders.h \
- encodersgui.h \
- tts.h \
- ttsgui.h \
- ../../tools/wavtrim.h \
- ../../tools/voicefont.h \
- voicefile.h \
- createvoicewindow.h \
- rbsettings.h \
- base/rbunzip.h \
- base/rbzip.h \
- sysinfo.h \
- base/detect.h \
- base/bootloaderinstallbase.h \
- base/bootloaderinstallmi4.h \
- base/bootloaderinstallhex.h \
- base/bootloaderinstallipod.h \
- base/bootloaderinstallsansa.h \
- base/bootloaderinstallfile.h \
- ../../tools/mkboot.h \
- ../../tools/iriver.h
+ install.h \
+ base/httpget.h \
+ configure.h \
+ zip/zip.h \
+ zip/unzip.h \
+ zip/zipentry_p.h \
+ zip/unzip_p.h \
+ zip/zip_p.h \
+ version.h \
+ installzip.h \
+ installtalkwindow.h \
+ talkfile.h \
+ base/autodetection.h \
+ progressloggerinterface.h \
+ progressloggergui.h \
+ ../ipodpatcher/ipodpatcher.h \
+ ../ipodpatcher/ipodio.h \
+ ../ipodpatcher/parttypes.h \
+ ../sansapatcher/sansapatcher.h \
+ ../sansapatcher/sansaio.h \
+ irivertools/h100sums.h \
+ irivertools/h120sums.h \
+ irivertools/h300sums.h \
+ browsedirtree.h \
+ installthemes.h \
+ base/uninstall.h \
+ uninstallwindow.h \
+ base/utils.h \
+ preview.h \
+ encoders.h \
+ encodersgui.h \
+ tts.h \
+ ttsgui.h \
+ ../../tools/wavtrim.h \
+ ../../tools/voicefont.h \
+ voicefile.h \
+ createvoicewindow.h \
+ rbsettings.h \
+ base/rbunzip.h \
+ base/rbzip.h \
+ sysinfo.h \
+ base/detect.h \
+ base/bootloaderinstallbase.h \
+ base/bootloaderinstallmi4.h \
+ base/bootloaderinstallhex.h \
+ base/bootloaderinstallipod.h \
+ base/bootloaderinstallsansa.h \
+ base/bootloaderinstallfile.h \
+ ../../tools/mkboot.h \
+ ../../tools/iriver.h
# Needed by QT on Win
-INCLUDEPATH = . irivertools zip zlib ../ipodpatcher ../sansapatcher ../../tools/rbspeex ../../tools
+INCLUDEPATH = . \
+ irivertools \
+ zip \
+ zlib \
+ ../ipodpatcher \
+ ../sansapatcher \
+ ../../tools/rbspeex \
+ ../../tools
INCLUDEPATH += base
-
-LIBS += -L../../tools/rbspeex -lrbspeex
-
+LIBS += -L../../tools/rbspeex \
+ -lrbspeex
TEMPLATE = app
-dbg {
- CONFIG += debug thread qt warn_on
+dbg {
+ CONFIG += debug \
+ thread \
+ qt \
+ warn_on
DEFINES -= QT_NO_DEBUG_OUTPUT
message("debug")
}
-!dbg {
- CONFIG += release thread qt
+!dbg {
+ CONFIG += release \
+ thread \
+ qt
DEFINES += QT_NO_DEBUG_OUTPUT
message("release")
}
-
TARGET = rbutilqt
-
-FORMS += rbutilqtfrm.ui \
- aboutbox.ui \
- installfrm.ui \
- progressloggerfrm.ui \
- configurefrm.ui \
- browsedirtreefrm.ui \
- installtalkfrm.ui \
- installthemesfrm.ui \
- uninstallfrm.ui \
- previewfrm.ui \
- rbspeexcfgfrm.ui \
- encexescfgfrm.ui \
- ttsexescfgfrm.ui \
- sapicfgfrm.ui \
- createvoicefrm.ui \
- sysinfofrm.ui
-
+FORMS += ttsfestivalcfgform.ui \
+ rbutilqtfrm.ui \
+ aboutbox.ui \
+ installfrm.ui \
+ progressloggerfrm.ui \
+ configurefrm.ui \
+ browsedirtreefrm.ui \
+ installtalkfrm.ui \
+ installthemesfrm.ui \
+ uninstallfrm.ui \
+ previewfrm.ui \
+ rbspeexcfgfrm.ui \
+ encexescfgfrm.ui \
+ ttsexescfgfrm.ui \
+ sapicfgfrm.ui \
+ createvoicefrm.ui \
+ sysinfofrm.ui
RESOURCES += rbutilqt.qrc
-win32 {
- RESOURCES += rbutilqt-win.qrc
-}
-!dbg {
- RESOURCES += rbutilqt-lang.qrc
-}
-
+win32:RESOURCES += rbutilqt-win.qrc
+!dbg:RESOURCES += rbutilqt-lang.qrc
TRANSLATIONS += lang/rbutil_de.ts \
- lang/rbutil_fi.ts \
- lang/rbutil_fr.ts \
- lang/rbutil_gr.ts \
- lang/rbutil_he.ts \
- lang/rbutil_ja.ts \
- lang/rbutil_nl.ts \
- lang/rbutil_pt.ts \
- lang/rbutil_tr.ts \
- lang/rbutil_zh_CN.ts \
- lang/rbutil_zh_TW.ts \
-
-
+ lang/rbutil_fi.ts \
+ lang/rbutil_fr.ts \
+ lang/rbutil_gr.ts \
+ lang/rbutil_he.ts \
+ lang/rbutil_ja.ts \
+ lang/rbutil_nl.ts \
+ lang/rbutil_pt.ts \
+ lang/rbutil_tr.ts \
+ lang/rbutil_zh_CN.ts \
+ lang/rbutil_zh_TW.ts
QT += network
-DEFINES += RBUTIL _LARGEFILE64_SOURCE
-
-win32 {
- SOURCES += ../ipodpatcher/ipodio-win32.c
- SOURCES += ../sansapatcher/sansaio-win32.c
+DEFINES += RBUTIL \
+ _LARGEFILE64_SOURCE
+win32 {
+ SOURCES += ../ipodpatcher/ipodio-win32.c
+ SOURCES += ../sansapatcher/sansaio-win32.c
RC_FILE = rbutilqt.rc
- LIBS += -lsetupapi -lnetapi32
+ LIBS += -lsetupapi \
+ -lnetapi32
}
-
-unix {
- SOURCES += ../ipodpatcher/ipodio-posix.c
- SOURCES += ../sansapatcher/sansaio-posix.c
+unix {
+ SOURCES += ../ipodpatcher/ipodio-posix.c
+ SOURCES += ../sansapatcher/sansaio-posix.c
}
-unix:!static {
- LIBS += -lusb
-}
-unix:static {
- # force statically linking of libusb. Libraries that are appended
- # later will get linked dynamically again.
- LIBS += -Wl,-Bstatic -lusb -Wl,-Bdynamic
-}
+unix:!static:LIBS += -lusb
+unix:static:# force statically linking of libusb. Libraries that are appended
-macx {
- QMAKE_MAC_SDK=/Developer/SDKs/MacOSX10.4u.sdk
- QMAKE_LFLAGS_PPC=-mmacosx-version-min=10.4 -arch ppc
- QMAKE_LFLAGS_X86=-mmacosx-version-min=10.4 -arch i386
- CONFIG+=x86 ppc
- LIBS += -L/usr/local/lib -framework IOKit
+# later will get linked dynamically again.
+LIBS += -Wl,-Bstatic \
+ -lusb \
+ -Wl,-Bdynamic
+macx {
+ QMAKE_MAC_SDK = /Developer/SDKs/MacOSX10.4u.sdk
+ QMAKE_LFLAGS_PPC = -mmacosx-version-min=10.4 \
+ -arch \
+ ppc
+ QMAKE_LFLAGS_X86 = -mmacosx-version-min=10.4 \
+ -arch \
+ i386
+ CONFIG += x86 \
+ ppc
+ LIBS += -L/usr/local/lib \
+ -framework \
+ IOKit
INCLUDEPATH += /usr/local/include
QMAKE_INFO_PLIST = Info.plist
RC_FILE = icons/rbutilqt.icns
# rule for creating a dmg file
- dmg.commands = hdiutil create -ov -srcfolder rbutilqt.app/ rbutil.dmg
+ dmg.commands = hdiutil \
+ create \
+ -ov \
+ -srcfolder \
+ rbutilqt.app/ \
+ rbutil.dmg
QMAKE_EXTRA_TARGETS += dmg
}
-
-static {
+static {
QTPLUGIN += qtaccessiblewidgets
- LIBS += -L$$(QT_BUILD_TREE)/plugins/accessible -lqtaccessiblewidgets
+ LIBS += -L$$(QT_BUILD_TREE)/plugins/accessible \
+ -lqtaccessiblewidgets
LIBS += -L.
DEFINES += STATIC
message("using static plugin")
}
-
-unix {
+unix {
target.path = /usr/local/bin
INSTALLS += target
}
-
-
-
Index: rbutil/rbutilqt/progressloggerinterface.h
===================================================================
--- rbutil/rbutilqt/progressloggerinterface.h (revision 20206)
+++ rbutil/rbutilqt/progressloggerinterface.h (working copy)
@@ -24,7 +24,7 @@
#include
-enum {
+enum LOGLEVEL {
LOGNOICON, LOGOK, LOGINFO, LOGWARNING, LOGERROR
};
Index: rbutil/rbutilqt/talkfile.h
===================================================================
--- rbutil/rbutilqt/talkfile.h (revision 20206)
+++ rbutil/rbutilqt/talkfile.h (working copy)
@@ -39,16 +39,17 @@
bool createTalkFiles(ProgressloggerInterface* logger);
void setSettings(RbSettings* sett) { settings = sett;}
-
+
void setDir(QDir dir){m_dir = dir; }
void setMountPoint(QString mountpoint) {m_mountpoint =mountpoint; }
+ void setIgnoreNonAscii(bool ov) {m_ignoreNonAscii = ov;}
void setOverwriteTalk(bool ov) {m_overwriteTalk = ov;}
void setRecursive(bool ov) {m_recursive = ov;}
void setStripExtensions(bool ov) {m_stripExtensions = ov;}
- void setTalkFolders(bool ov) {m_talkFolders = ov;}
+ void setTalkFolders(bool ov) {m_talkFolders = ov;}
void setTalkFiles(bool ov) {m_talkFiles = ov;}
-
+
private slots:
void abort();
@@ -58,24 +59,25 @@
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);
+ TTSStatus voiceList(QStringList toSpeak,QStringList& voicedEntries);
+ bool encodeList(QStringList toEncode,QStringList& encodedEntries);
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_recursive;
bool m_stripExtensions;
bool m_talkFolders;
bool m_talkFiles;
+ bool m_ignoreNonAscii;
ProgressloggerInterface* m_logger;
Index: rbutil/rbutilqt/voicefile.cpp
===================================================================
--- rbutil/rbutilqt/voicefile.cpp (revision 20206)
+++ rbutil/rbutilqt/voicefile.cpp (working copy)
@@ -39,15 +39,15 @@
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/";
-
+
+ m_path = QDir::tempPath() + "/rbvoice/";
+
// read rockbox-info.txt
QFile info(m_mountpoint+"/.rockbox/rockbox-info.txt");
if(!info.open(QIODevice::ReadOnly))
@@ -57,11 +57,11 @@
emit done(false);
return false;
}
-
+
QString target, features,version;
while (!info.atEnd()) {
QString line = info.readLine();
-
+
if(line.contains("Target:"))
{
target = line.remove("Target:").trimmed();
@@ -77,13 +77,13 @@
}
}
info.close();
-
+
//prepare download url
QUrl genlangUrl = settings->genlangUrl() +"?lang=" +m_lang+"&t="+target+"&rev="+version+"&f="+features;
-
+
qDebug() << "downloading " << genlangUrl;
-
- //download the correct genlang output
+
+ //download the correct genlang output
QTemporaryFile *downloadFile = new QTemporaryFile(this);
downloadFile->open();
filename = downloadFile->fileName();
@@ -91,11 +91,11 @@
// 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;
}
@@ -127,9 +127,9 @@
}
else m_logger->addItem(tr("Download finished."),LOGOK);
QCoreApplication::processEvents();
-
-
- m_logger->setProgressMax(0);
+
+
+ m_logger->setProgressMax(0);
//open downloaded file
QFile genlang(filename);
if(!genlang.open(QIODevice::ReadOnly))
@@ -138,12 +138,12 @@
m_logger->abort();
emit done(false);
return;
- }
+ }
//tts
- m_tts = TTSBase::getTTS(settings->curTTS());
+ m_tts = TTSBase::getTTS(settings->curTTS());
m_tts->setCfg(settings);
-
+
QString errStr;
if(!m_tts->start(&errStr))
{
@@ -155,9 +155,9 @@
}
// Encoder
- m_enc = EncBase::getEncoder(settings->curEncoder());
+ m_enc = EncBase::getEncoder(settings->curEncoder());
m_enc->setCfg(settings);
-
+
if(!m_enc->start())
{
m_logger->addItem(tr("Init of Encoder engine failed"),LOGERROR);
@@ -169,15 +169,15 @@
QCoreApplication::processEvents();
connect(m_logger,SIGNAL(aborted()),this,SLOT(abort()));
-
+
//read in downloaded file
- QList > voicepairs;
+ QList > voicepairs;
QTextStream in(&genlang);
in.setCodec("UTF-8");
QString id, voice;
bool idfound = false;
bool voicefound=false;
- while (!in.atEnd())
+ while (!in.atEnd())
{
QString line = in.readLine();
if(line.contains("id:")) //ID found
@@ -190,82 +190,85 @@
voice = line.remove("voice:").remove('"').trimmed();
voicefound=true;
}
-
+
if(idfound && voicefound)
{
voicepairs.append(QPair(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->addItem(tr("The downloaded file was empty!"),LOGERROR);
m_logger->abort();
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->addItem("aborted.",LOGERROR);
m_logger->abort();
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();
- m_tts->voice(toSpeak,wavname); // generate wav
+
+ // 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
+
+ // encode wav
m_enc->encode(wavname,encodedname);
- // remove the wav file
+ // remove the wav file
QFile::remove(wavname);
// remember the mp3 file for later removing
mp3files << encodedname;
}
-
-
- //make voicefile
+
+
+ //make voicefile
FILE* ids2 = fopen(filename.toUtf8(), "r");
if (ids2 == NULL)
{
- m_logger->addItem(tr("Error opening downloaded file"),LOGERROR);
+ m_logger->addItem(tr("Error opening downloaded file"),LOGERROR);
m_logger->abort();
emit done(false);
return;
@@ -274,32 +277,32 @@
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);
+ 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.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->abort();
+ m_logger->addItem(tr("successfully created."),LOGOK);
+ m_logger->abort();
- emit done(true);
+ emit done(true);
}
void VoiceFileCreator::updateDataReadProgress(int read, int total)
Index: rbutil/rbutilqt/installtalkwindow.cpp
===================================================================
--- rbutil/rbutilqt/installtalkwindow.cpp (revision 20206)
+++ rbutil/rbutilqt/installtalkwindow.cpp (working copy)
@@ -65,22 +65,22 @@
{
Config *cw = new Config(this,4);
cw->setSettings(settings);
-
+
connect(cw, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
-
+
cw->show();
}
void InstallTalkWindow::accept()
{
logger = new ProgressLoggerGui(this);
-
+
connect(logger,SIGNAL(closed()),this,SLOT(close()));
logger->show();
-
+
QString folderToTalk = ui.lineTalkFolder->text();
-
+
if(!QFileInfo(folderToTalk).isDir())
{
logger->addItem(tr("The Folder to Talk is wrong!"),LOGERROR);
@@ -95,13 +95,14 @@
talkcreator->setSettings(settings);
talkcreator->setDir(QDir(folderToTalk));
talkcreator->setMountPoint(settings->mountpoint());
-
+
+ talkcreator->setIgnoreNonAscii(ui.IgnoreNonAscii->isChecked());
talkcreator->setOverwriteTalk(ui.OverwriteTalk->isChecked());
talkcreator->setRecursive(ui.recursive->isChecked());
talkcreator->setStripExtensions(ui.StripExtensions->isChecked());
talkcreator->setTalkFolders(ui.talkFolders->isChecked());
talkcreator->setTalkFiles(ui.talkFiles->isChecked());
-
+
talkcreator->createTalkFiles(logger);
}
@@ -124,7 +125,7 @@
else
ui.labelTtsProfile->setText(tr("Selected TTS engine: %1")
.arg("Invalid TTS configuration!"));
-
+
QString encoder = settings->curEncoder();
EncBase* enc = EncBase::getEncoder(encoder);
if(enc != NULL) {
Index: rbutil/rbutilqt/tts.h
===================================================================
--- rbutil/rbutilqt/tts.h (revision 20206)
+++ rbutil/rbutilqt/tts.h (working copy)
@@ -19,13 +19,15 @@
*
****************************************************************************/
-
+
#ifndef TTS_H
#define TTS_H
#include "rbsettings.h"
#include
+#include
+#include
#ifndef CONSOLE
#include "ttsgui.h"
@@ -33,30 +35,38 @@
#include "ttsguicli.h"
#endif
-
+enum TTSStatus{ FatalError, NoError, Warning };
class TTSBase : public QObject
{
Q_OBJECT
public:
TTSBase();
- virtual bool voice(QString text,QString wavfile)
- { (void)text; (void)wavfile; return false; }
+ virtual TTSStatus voice(QString text,QString wavfile, QString* errStr, bool ignoreNonAscii = false)
+ {
+ if(ignoreNonAscii && !isASCII(text))
+ {
+ *errStr = tr("Ignored non-ASCII text.");
+ return Warning;
+ }
+
+ (void)wavfile; (void) errStr; return FatalError;
+ }
virtual bool start(QString *errStr) { (void)errStr; return false; }
virtual bool stop() { return false; }
virtual void showCfg(){}
virtual bool configOk() { return false; }
virtual void setCfg(RbSettings* sett) { settings = sett; }
-
+
static TTSBase* getTTS(QString ttsname);
static QStringList getTTSList();
static QString getTTSName(QString tts);
-
+
public slots:
virtual void accept(void){}
virtual void reject(void){}
virtual void reset(void){}
-
+
private:
//inits the tts List
static void initTTSList();
@@ -65,6 +75,7 @@
RbSettings* settings;
static QMap ttsList;
static QMap ttsCache;
+ bool isASCII(const QString str);
};
class TTSSapi : public TTSBase
@@ -72,18 +83,18 @@
Q_OBJECT
public:
TTSSapi();
- virtual bool voice(QString text,QString wavfile);
+ virtual TTSStatus voice(QString text,QString wavfile, QString *errStr, bool ignoreNonAscii = false);
virtual bool start(QString *errStr);
virtual bool stop();
virtual void showCfg();
virtual bool configOk();
-
+
QStringList getVoiceList(QString language);
private:
QProcess* voicescript;
QTextStream* voicestream;
QString defaultLanguage;
-
+
QString m_TTSexec;
QString m_TTSOpts;
QString m_TTSTemplate;
@@ -99,14 +110,14 @@
Q_OBJECT
public:
TTSExes(QString name);
- virtual bool voice(QString text,QString wavfile);
+ virtual TTSStatus voice(QString text,QString wavfile, QString *errStr, bool ignoreNonAscii = false);
virtual bool start(QString *errStr);
virtual bool stop() {return true;}
virtual void showCfg();
virtual bool configOk();
virtual void setCfg(RbSettings* sett);
-
+
private:
QString m_name;
QString m_TTSexec;
@@ -115,4 +126,23 @@
QMap m_TemplateMap;
};
+class TTSFestival : public TTSBase
+{
+ Q_OBJECT
+public:
+ TTSFestival();
+ virtual bool configOk();
+ virtual bool start(QString *errStr);
+ virtual bool stop();
+ virtual void showCfg();
+ virtual void setCfg(RbSettings* sett);
+ virtual TTSStatus voice(QString text,QString wavfile, QString *errStr, bool ignoreNonAscii = false);
+
+ QStringList getVoiceList();
+private:
+ void startServer();
+ void ensureServerRunning();
+ QProcess serverProcess;
+ QStringList voices;
+};
#endif
Index: rbutil/rbutilqt/installtalkfrm.ui
===================================================================
--- rbutil/rbutilqt/installtalkfrm.ui (revision 20206)
+++ rbutil/rbutilqt/installtalkfrm.ui (working copy)
@@ -125,7 +125,7 @@
- -
+
-
Overwrite Talkfiles
@@ -158,14 +158,14 @@
+ -
+
+
+ Ignore filenames with non-ASCII characters
+
+
+
- recursive
- StripExtensions
- OverwriteTalk
- talkFolders
- talkFiles
- label_3
- fileFilter
-
Index: rbutil/rbutilqt/ttsgui.h
===================================================================
--- rbutil/rbutilqt/ttsgui.h (revision 20206)
+++ rbutil/rbutilqt/ttsgui.h (working copy)
@@ -26,16 +26,18 @@
#include "ui_ttsexescfgfrm.h"
#include "ui_sapicfgfrm.h"
+#include "ui_ttsfestivalcfgform.h"
class RbSettings;
class TTSSapi;
+class TTSFestival;
class TTSSapiGui : public QDialog
{
Q_OBJECT
public:
TTSSapiGui(TTSSapi* sapi,QDialog* parent = NULL);
-
+
void showCfg();
void setCfg(RbSettings* sett){settings = sett;}
public slots:
@@ -56,14 +58,14 @@
Q_OBJECT
public:
TTSExesGui(QDialog* parent = NULL);
-
+
void showCfg(QString m_name);
void setCfg(RbSettings* sett){settings = sett;}
public slots:
virtual void accept(void);
virtual void reject(void);
- virtual void reset(void);
+ virtual void reset(void);
void browse(void);
private:
Ui::TTSExesCfgFrm ui;
@@ -71,4 +73,23 @@
QString m_name;
};
+class TTSFestivalGui : public QDialog
+{
+ Q_OBJECT
+public:
+ TTSFestivalGui(TTSFestival* festival, QDialog* parent = NULL);
+
+ void showCfg();
+ void setCfg(RbSettings* sett){settings = sett;}
+
+ public slots:
+ virtual void accept(void);
+ virtual void reject(void);
+ //virtual void reset(void);
+ void updateVoices();
+ private:
+ Ui::TTSFestivalCfgFrm ui;
+ RbSettings* settings;
+ TTSFestival* festival;
+};
#endif
Index: rbutil/rbutilqt/talkfile.cpp
===================================================================
--- rbutil/rbutilqt/talkfile.cpp (revision 20206)
+++ rbutil/rbutilqt/talkfile.cpp (working copy)
@@ -24,25 +24,25 @@
}
-//! \brief Creates Talkfiles.
+//! \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;
+ QStringList toSpeakList, voicedEntries, encodedEntries;
QString errStr;
-
+
m_logger->addItem(tr("Starting Talk file generation"),LOGINFO);
-
+
//tts
- m_tts = TTSBase::getTTS(settings->curTTS());
+ m_tts = TTSBase::getTTS(settings->curTTS());
m_tts->setCfg(settings);
-
+
if(!m_tts->start(&errStr))
{
m_logger->addItem(errStr.trimmed(),LOGERROR);
@@ -52,9 +52,9 @@
}
// Encoder
- m_enc = EncBase::getEncoder(settings->curEncoder());
+ m_enc = EncBase::getEncoder(settings->curEncoder());
m_enc->setCfg(settings);
-
+
if(!m_enc->start())
{
m_logger->addItem(tr("Init of Encoder engine failed"),LOGERROR);
@@ -67,7 +67,7 @@
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)
@@ -76,21 +76,21 @@
doAbort(toSpeakList);
return false;
}
-
+
// create List of all Files/Dirs to speak
QMapIterator dirIt(dirList);
- while (dirIt.hasNext())
+ 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());
+ toSpeakList.append(dirIt.value());
}
}
QMapIterator fileIt(fileList);
- while (fileIt.hasNext())
+ while (fileIt.hasNext())
{
fileIt.next();
// insert only non- dublictae file entries into list
@@ -99,46 +99,45 @@
if(m_stripExtensions)
toSpeakList.append(stripExtension(fileIt.value()));
else
- toSpeakList.append(fileIt.value());
+ toSpeakList.append(fileIt.value());
}
}
-
- // Voice entryies
+
+ // Voice entries
m_logger->addItem(tr("Voicing entries..."),LOGINFO);
- if(voiceList(toSpeakList,&errStr) == false)
+ TTSStatus voiceStatus= voiceList(toSpeakList,voicedEntries);
+ if(voiceStatus == FatalError)
{
- m_logger->addItem(errStr,LOGERROR);
- doAbort(toSpeakList);
+ doAbort(toSpeakList);
return false;
}
-
+
// Encoding Entries
m_logger->addItem(tr("Encoding files..."),LOGINFO);
- if(encodeList(toSpeakList,&errStr) == false)
+ if(encodeList(voicedEntries,encodedEntries) == false)
{
- m_logger->addItem(errStr,LOGERROR);
doAbort(toSpeakList);
return false;
}
-
- // Copying talk files
+
+ // Copying talk files
m_logger->addItem(tr("Copying Talkfile for Dirs..."),LOGINFO);
if(copyTalkDirFiles(dirList,&errStr) == false)
{
m_logger->addItem(errStr,LOGERROR);
- doAbort(toSpeakList);
+ 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);
+ doAbort(toSpeakList);
return false;
}
-
+
// Deleting left overs
if( !cleanup(toSpeakList))
return false;
@@ -185,7 +184,7 @@
m_logger->setProgressValue(0);
m_logger->abort();
m_tts->stop();
- m_enc->stop();
+ m_enc->stop();
}
//! \brief Creates MultiMaps (paths -> File/dir names) of all Dirs and Files in a Folder.
@@ -195,16 +194,16 @@
//! \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.
+//! \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(startDir,flags);
-
+
// read in Maps of paths - file/dirnames
while (it.hasNext())
{
@@ -213,14 +212,14 @@
{
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)
{
@@ -239,7 +238,7 @@
}
QCoreApplication::processEvents();
}
- return true;
+ return true;
}
//! \brief Voices a List of string to the temp dir. Progress is handled inside.
@@ -247,59 +246,76 @@
//! \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
-bool TalkFileCreator::voiceList(QStringList toSpeak,QString* errString)
+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)
{
- *errString = tr("Talk file creation aborted");
- return false;
+ m_logger->addItem(tr("Talk file creation aborted"), LOGERROR);
+ return FatalError;
}
-
+
QString filename = QDir::tempPath()+ "/"+ toSpeak[i] + ".wav";
-
- if(!m_tts->voice(toSpeak[i],filename))
+
+ QString error;
+ TTSStatus status = m_tts->voice(toSpeak[i],filename, &error, m_ignoreNonAscii);
+ if( status == Warning)
{
- *errString =tr("Voicing of %s failed").arg(toSpeak[i]);
- return false;
- }
+ 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();
}
- return true;
+ 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"
+//! 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,QString* errString)
+bool TalkFileCreator::encodeList(QStringList toEncode,QStringList& encodedEntries)
{
resetProgress(toEncode.size());
for(int i=0; i < toEncode.size(); i++)
{
if(m_abort)
{
- *errString = tr("Talk file creation aborted");
+ 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))
{
- *errString =tr("Encoding of %1 failed").arg(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();
+ QCoreApplication::processEvents();
}
return true;
}
@@ -308,16 +324,16 @@
//!
//! \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
+//! \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())
+ while (it.hasNext())
{
it.next();
if(m_abort)
@@ -325,47 +341,51 @@
*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;
+ 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
+//! \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())
+ while (it.hasNext())
{
it.next();
if(m_abort)
@@ -373,55 +393,58 @@
*errString = tr("Talk file creation aborted");
return false;
}
-
+
QString source;
QString target = it.key() + "/" + it.value() + ".talk";
-
- // correct source if we hav stripExtension enabled
+
+ // correct source if we hav stripExtension enabled
if(m_stripExtensions)
- source = QDir::tempPath()+ "/"+ stripExtension(it.value()) + ".talk";
+ 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;
+ 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;