rbutil: Rework TTS classes to use a stringlist for arguments

Instead of passing the entire cmdline as a single string that was
treated as the exectuable name on some platforms

Change-Id: Ic4f043a3a48e1b1bfab82bbfa8983c2d224606ec
This commit is contained in:
Solomon Peachy 2026-07-09 14:41:54 -04:00
parent a9a4b3316f
commit 390d17893f
10 changed files with 87 additions and 53 deletions

View file

@ -33,8 +33,15 @@ class TTSEspeak : public TTSExes
m_name = "espeak";
/* default to espeak */
m_TTSTemplate = "\"%exe\" %options -w \"%wavfile\" -- \"%text\"";
m_TTSSpeakTemplate = "\"%exe\" %options -- \"%text\"";
m_TTSTemplate << "%options";
m_TTSTemplate << "-w";
m_TTSTemplate << "%wavfile";
m_TTSTemplate << "--";
m_TTSTemplate << "%text";
m_TTSSpeakTemplate << "%options";
m_TTSSpeakTemplate << "--";
m_TTSSpeakTemplate << "%text";
m_capabilities = TTSBase::CanSpeak;
}
};

View file

@ -32,8 +32,15 @@ class TTSEspeakNG : public TTSExes
{
m_name = "espeak-ng";
m_TTSTemplate = "\"%exe\" %options -w \"%wavfile\" -- \"%text\"";
m_TTSSpeakTemplate = "\"%exe\" %options -- \"%text\"";
m_TTSTemplate << "%options";
m_TTSTemplate << "-w";
m_TTSTemplate << "%wavfile";
m_TTSTemplate << "--";
m_TTSTemplate << "%text";
m_TTSSpeakTemplate << "%options";
m_TTSSpeakTemplate << "--";
m_TTSSpeakTemplate << "%text";
m_capabilities = TTSBase::CanSpeak;
}
};

View file

@ -24,14 +24,10 @@
TTSExes::TTSExes(QObject* parent) : TTSBase(parent)
{
/* default to espeak */
m_name = "espeak";
m_capabilities = TTSBase::CanSpeak;
m_TTSTemplate = "\"%exe\" %options -w \"%wavfile\" -- \"%text\"";
m_TTSSpeakTemplate = "\"%exe\" %options -- \"%text\"";
m_name = "false";
m_capabilities = TTSBase::None;
}
TTSBase::Capabilities TTSExes::capabilities()
{
return m_capabilities;
@ -83,14 +79,14 @@ bool TTSExes::start(QString *errStr)
TTSStatus TTSExes::voice(const QString& text, const QString& wavfile, QString *errStr)
{
(void) errStr;
QString execstring;
QStringList exec;
if(wavfile.isEmpty() && m_capabilities & TTSBase::CanSpeak) {
if(m_TTSSpeakTemplate.isEmpty()) {
LOG_ERROR() << "internal error: TTS announces CanSpeak "
"but template empty!";
return FatalError;
}
execstring = m_TTSSpeakTemplate;
exec = m_TTSSpeakTemplate;
}
else if(wavfile.isEmpty()) {
LOG_ERROR() << "no output file passed to voice() "
@ -98,15 +94,19 @@ TTSStatus TTSExes::voice(const QString& text, const QString& wavfile, QString *e
return FatalError;
}
else {
execstring = m_TTSTemplate;
exec = m_TTSTemplate;
}
execstring.replace("%exe",m_TTSexec);
execstring.replace("%options",m_TTSOpts);
execstring.replace("%wavfile",wavfile);
execstring.replace("%text",text);
exec.replaceInStrings("%options",m_TTSOpts);
exec.replaceInStrings("%wavfile",wavfile);
exec.replaceInStrings("%text",text);
QProcess::execute(execstring);
int ret;
if ((ret = QProcess::execute(m_TTSexec, exec))) {
LOG_ERROR() << "TTS exec failed (" << ret << "): " << m_TTSexec << " " << exec;
return FatalError;
}
if(!wavfile.isEmpty() && !QFileInfo(wavfile).isFile()) {
LOG_ERROR() << "output file does not exist:" << wavfile;
@ -124,4 +124,3 @@ bool TTSExes::configOk()
else
return false;
}

View file

@ -50,8 +50,8 @@ class TTSExes : public TTSBase
void loadSettings(void);
protected:
QString m_TTSTemplate;
QString m_TTSSpeakTemplate;
QStringList m_TTSTemplate;
QStringList m_TTSSpeakTemplate;
QString m_name;
QString m_TTSexec;
QString m_TTSOpts;

View file

@ -32,11 +32,14 @@ class TTSFlite : public TTSExes
{
m_name = "flite";
/* default to espeak */
m_TTSTemplate = "\"%exe\" %options -o \"%wavfile\" -t \"%text\"";
m_TTSSpeakTemplate = "";
m_capabilities = TTSBase::None;
m_TTSTemplate << "%options";
m_TTSTemplate << "-o";
m_TTSTemplate << "%wavfile";
m_TTSTemplate << "-t";
m_TTSTemplate << "%text";
//m_TTSSpeakTemplate << "";
m_capabilities = TTSBase::None;
}
};

View file

@ -32,8 +32,15 @@ class TTSMimic : public TTSExes
{
m_name = "mimic";
m_TTSTemplate = "\"%exe\" %options -o \"%wavfile\" -t \"%text\"";
m_TTSSpeakTemplate = "\"%exe\" %options -t \"%text\"";
m_TTSTemplate << "%options";
m_TTSTemplate << "-o";
m_TTSTemplate << "%wavfile";
m_TTSTemplate << "-t";
m_TTSTemplate << "%text";
m_TTSSpeakTemplate << "%options";
m_TTSSpeakTemplate << "-t";
m_TTSSpeakTemplate << "%text";
m_capabilities = TTSBase::CanSpeak;
}
};

View file

@ -30,14 +30,10 @@ class TTSMssp: public TTSSapi
public:
TTSMssp(QObject* parent=nullptr) : TTSSapi(parent)
{
m_TTSTemplate = "cscript //nologo \"%exe\" "
"/language:%lang /voice:\"%voice\" "
"/speed:%speed \"%options\" /mssp";
m_TTSVoiceTemplate = "cscript //nologo \"%exe\" "
"/language:%lang /listvoices /mssp";
m_TTSTemplate << "/mssp";
m_TTSVoiceTemplate << "/mssp";
m_TTSType = "mssp";
}
};
#endif

View file

@ -24,9 +24,18 @@
TTSSapi::TTSSapi(QObject* parent) : TTSBase(parent)
{
m_TTSTemplate = "cscript //nologo \"%exe\" /language:%lang "
"/voice:\"%voice\" /speed:%speed \"%options\"";
m_TTSVoiceTemplate = "cscript //nologo \"%exe\" /language:%lang /listvoices";
m_TTSTemplate << "//nologo";
m_TTSTemplate << "%exe";
m_TTSTemplate << "/language:%lang";
m_TTSTemplate << "/voice:%voice";
m_TTSTemplate << "/speed:%speed";
m_TTSTemplate << "%options";
m_TTSVoiceTemplate << "//nologo";
m_TTSVoiceTemplate << "%exe";
m_TTSVoiceTemplate << "/language:%lang";
m_TTSVoiceTemplate << "/listvoices";
m_TTSType = "sapi";
defaultLanguage = "english";
m_started = false;
@ -113,17 +122,17 @@ bool TTSSapi::start(QString *errStr)
return false;
}
// create the voice process
QString execstring = m_TTSTemplate;
execstring.replace("%exe",m_TTSexec);
execstring.replace("%options",m_TTSOpts);
execstring.replace("%lang",m_TTSLanguage);
execstring.replace("%voice",m_TTSVoice);
execstring.replace("%speed",m_TTSSpeed);
QStringList exec = m_TTSTemplate;
exec.replaceInStrings("%exe",m_TTSexec);
exec.replaceInStrings("%options",m_TTSOpts);
exec.replaceInStrings("%lang",m_TTSLanguage);
exec.replaceInStrings("%voice",m_TTSVoice);
exec.replaceInStrings("%speed",m_TTSSpeed);
LOG_INFO() << "Start:" << execstring;
LOG_INFO() << "Start: cscript " << exec;
voicescript = new QProcess(nullptr);
//connect(voicescript,SIGNAL(readyReadStandardError()),this,SLOT(error()));
voicescript->start(execstring);
voicescript->start("cscript", exec);
LOG_INFO() << "wait for process";
if(!voicescript->waitForStarted())
{
@ -178,13 +187,13 @@ QStringList TTSSapi::getVoiceList(QString language)
return result;
// create the voice process
QString execstring = m_TTSVoiceTemplate;
execstring.replace("%exe",m_TTSexec);
execstring.replace("%lang",language);
QStringList exec = m_TTSVoiceTemplate;
exec.replaceInStrings("%exe",m_TTSexec);
exec.replaceInStrings("%lang",language);
LOG_INFO() << "Start:" << execstring;
LOG_INFO() << "Start: cscript " << exec;
voicescript = new QProcess(nullptr);
voicescript->start(execstring);
voicescript->start("cscript", exec);
LOG_INFO() << "wait for process";
if(!voicescript->waitForStarted()) {
LOG_INFO() << "process startup timed out!";

View file

@ -67,8 +67,8 @@ class TTSSapi : public TTSBase
bool m_started;
protected:
QString m_TTSTemplate;
QString m_TTSVoiceTemplate;
QStringList m_TTSTemplate;
QStringList m_TTSVoiceTemplate;
QString m_TTSType;
};

View file

@ -31,8 +31,14 @@ class TTSSwift : public TTSExes
TTSSwift(QObject* parent=nullptr) : TTSExes(parent)
{
m_name = "swift";
m_TTSTemplate = "\"%exe\" %options -o \"%wavfile\" -- \"%text\"";
m_TTSSpeakTemplate = "";
m_TTSTemplate << "%options";
m_TTSTemplate << "-o";
m_TTSTemplate << "%wavfile";
m_TTSTemplate << "--";
m_TTSTemplate << "%text";
//m_TTSSpeakTemplate << "";
m_capabilities = TTSBase::None;
}
};