From: Modestas Vainius <modax@debian.org>
Subject: Properly support permanent storage of kttsd talker settings, jobmgr fixes.
Origin: vendor
Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=599825
Last-Update: 2010-12-04
Forwarded: no
This patch builds on top of the upstream jobmgr patch (commits 1072198,
1138400) and:
1) adds support for permanent storage (to config file) of talker settings in
both KTTS daemon and its configuration GUI. This includes saving and loading of
the settings;
2) brings job manager GUI to a usable state rather than half-ported and hardly
working bunch of GUI elements. Not entirely bug-free, but usable (i.e. should
be RC bug free).
--- a/kttsd/kcmkttsmgr/kcmkttsmgr.cpp
+++ b/kttsd/kcmkttsmgr/kcmkttsmgr.cpp
@@ -498,6 +498,10 @@ void KCMKttsMgr::load()
m_changed = false;
m_suppressConfigChanged = false;
+
+ // load the first talker into job manager
+ if (m_jobMgrWidget && m_talkerListModel.rowCount() > 0)
+ m_jobMgrWidget->load(m_talkerListModel.getRow(0));
}
/**
@@ -592,12 +596,16 @@ void KCMKttsMgr::save()
m_config->sync();
- // apply changes in the jobs page if it exists
+ // schedule apply of the changes in the jobs page once kttsd restarts
if (m_jobMgrWidget)
{
- m_jobMgrWidget->save();
+ m_jobMgrWidget->setSavePending(true);
+ //m_jobMgrWidget->save();
}
+ // Restart kttsd in order to pick up talker changes from config file
+ m_kspeech->reinit();
+
// If we automatically unchecked the Enable KTTSD checkbox, stop KTTSD.
if (enableKttsdWasToggled)
slotEnableKttsd_toggled(false);
@@ -1033,6 +1041,9 @@ void KCMKttsMgr::updateTalkerButtons(){
configureTalkerButton->setEnabled(true);
higherTalkerPriorityButton->setEnabled(modelIndex.row() != 0);
lowerTalkerPriorityButton->setEnabled(modelIndex.row() < (m_talkerListModel.rowCount() - 1));
+ // Update output module and language in jobMgrWidget
+ if (m_jobMgrWidget)
+ m_jobMgrWidget->load(m_talkerListModel.getRow(modelIndex.row()));
} else {
removeTalkerButton->setEnabled(false);
configureTalkerButton->setEnabled(false);
@@ -1140,6 +1151,13 @@ void KCMKttsMgr::kttsdStarted()
// Check/Uncheck the Enable KTTSD check box.
if (kttsdLoaded)
{
+ bool reinit = false;
+ if (m_kspeech) { // already connected, reinit called
+ // disconnect first
+ disconnect( QDBusConnection::sessionBus().interface(), 0, this, 0 );
+ delete m_kspeech;
+ reinit = true;
+ }
enableKttsdCheckBox->setChecked(true);
m_kspeech = new OrgKdeKSpeechInterface("org.kde.kttsd", "/KSpeech", QDBusConnection::sessionBus());
m_kspeech->setParent(this);
@@ -1157,6 +1175,8 @@ void KCMKttsMgr::kttsdStarted()
kttsdVersion->setText(i18n("KTTSD Version: %1", m_kspeech->version()));
+ if (!reinit)
+ m_jobMgrWidget->load(TalkerCode());
} else {
enableKttsdCheckBox->setChecked(false);
delete m_kspeech;
--- a/kttsd/kcmkttsmgr/kttsjobmgr.cpp
+++ b/kttsd/kcmkttsmgr/kttsjobmgr.cpp
@@ -56,7 +56,8 @@
#include "selecttalkerdlg.h"
KttsJobMgr::KttsJobMgr(QWidget *parent) :
- QWidget(parent)
+ QWidget(parent),
+ m_savePending(false)
{
m_ui = new Ui::kttsjobmgr;
m_ui->setupUi(this);
@@ -77,7 +78,7 @@ KttsJobMgr::KttsJobMgr(QWidget *parent)
connect (m_ui->volumeSlider, SIGNAL(valueChanged(int)), this, SIGNAL(configChanged()));
connect (m_ui->moduleComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(slot_moduleChanged(const QString &)));
- connect (m_ui->languageComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(slot_languageChanged(const QString &)));
+ connect (m_ui->languageComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slot_languageChanged(int)));
connect (m_ui->voiceComboBox, SIGNAL(currentIndexChanged(int)), this, SIGNAL(configChanged()));
m_ui->stopButton->setIcon(KIcon("media-playback-stop"));
@@ -139,25 +140,104 @@ void KttsJobMgr::slot_resume()
void KttsJobMgr::save()
{
+ if (m_ui->moduleComboBox->currentIndex() > -1)
+ m_kspeech->setOutputModule(m_ui->moduleComboBox->currentText());
+ if (m_ui->languageComboBox->currentIndex() > -1)
+ {
+ int langIndex = m_ui->languageComboBox->currentIndex();
+ m_kspeech->setLanguage(m_ui->languageComboBox->itemData(langIndex).toString());
+ }
m_kspeech->setSpeed(m_ui->speedSlider->value());
m_kspeech->setPitch(m_ui->pitchSlider->value());
m_kspeech->setVolume(m_ui->volumeSlider->value());
m_kspeech->setVoiceType(m_ui->voiceComboBox->currentIndex() + 1);
+
+ m_savePending = false;
+}
+
+void KttsJobMgr::load(const TalkerCode & tc, bool complete)
+{
+ m_ui->moduleComboBox->clear();
+ bool wasSet = false;
+ QStringList modules = m_kspeech->outputModules();
+ int i = 0;
+
+ foreach (const QString module, modules)
+ {
+ m_ui->moduleComboBox->addItem(module);
+ if (module == tc.outputModule())
+ {
+ m_ui->moduleComboBox->setCurrentIndex(i);
+ wasSet = true;
+ }
+ i++;
+ }
+ if (wasSet)
+ {
+ if (complete) {
+ loadLanguages(tc.language());
+ m_ui->voiceComboBox->setCurrentIndex(tc.voiceType()-1);
+ m_ui->speedSlider->setValue(tc.rate());
+ m_ui->pitchSlider->setValue(tc.pitch());
+ m_ui->volumeSlider->setValue(tc.volume());
+ }
+ }
+ else
+ {
+ m_ui->moduleComboBox->setCurrentIndex(-1);
+ }
}
-void KttsJobMgr::load()
+void KttsJobMgr::loadLanguages(const QString & selectedLanguage)
{
+ QString module = m_ui->moduleComboBox->currentText();
+ m_ui->languageComboBox->clear();
+ if (!module.isEmpty())
+ {
+ int i = 0;
+ bool wasSet = false;
+ QStringList languages = m_kspeech->languagesByModule(module);
+ foreach (const QString language, languages)
+ {
+ QString langName = TalkerCode::languageCodeToLanguage(language);
+ QString langLabel = (langName.isEmpty()) ? language :
+ QString("%1 (%2)").arg(langName).arg(language);
+ m_ui->languageComboBox->addItem(langLabel, language);
+ if (language == selectedLanguage)
+ {
+ m_ui->languageComboBox->setCurrentIndex(i);
+ wasSet = true;
+ }
+ i++;
+ }
+ if (!wasSet) m_ui->languageComboBox->setCurrentIndex(-1);
+ }
}
void KttsJobMgr::slot_moduleChanged(const QString & module)
{
+ if (module.isEmpty()) {
+ m_ui->languageComboBox->clear();
+ return;
+ }
+
kDebug() << "changing the output module to " << module;
m_kspeech->setOutputModule(module);
+
+ QString fullLanguageCode = KGlobal::locale()->defaultLanguage();
+ QString languageCode, countryCode;
+ TalkerCode::splitFullLanguageCode(fullLanguageCode, languageCode, countryCode);
+ loadLanguages(languageCode);
+
emit configChanged();
}
-void KttsJobMgr::slot_languageChanged(const QString & language)
+void KttsJobMgr::slot_languageChanged(int index)
{
+ if (index < 0)
+ return;
+
+ QString language = m_ui->languageComboBox->itemData(index).toString();
kDebug() << "changing the language to " << language;
m_kspeech->setLanguage(language);
emit configChanged();
@@ -261,6 +341,16 @@ QString KttsJobMgr::cachedTalkerCodeToTa
}
}
+void KttsJobMgr::setSavePending(bool value)
+{
+ m_savePending = value;
+}
+
+bool KttsJobMgr::isSavePending()
+{
+ return m_savePending;
+}
+
/** Slots connected to DBUS Signals emitted by KTTSD. */
/**
@@ -268,4 +358,6 @@ QString KttsJobMgr::cachedTalkerCodeToTa
*/
Q_SCRIPTABLE void KttsJobMgr::kttsdStarted()
{
+ if (isSavePending())
+ save();
}
--- a/kttsd/kcmkttsmgr/kttsjobmgr.h
+++ b/kttsd/kcmkttsmgr/kttsjobmgr.h
@@ -37,6 +37,7 @@ class KPushButton;
class KttsJobMgrBrowserExtension;
class JobInfo;
class JobInfoListModel;
+class TalkerCode;
namespace Ui
{
@@ -54,7 +55,10 @@ public:
/** apply current settings, i.e. speech-dispatcher what to do */
void save();
/** get the current settings from speech-dispatcher */
- void load();
+ void load(const TalkerCode & tc, bool complete = true);
+
+ void setSavePending(bool value);
+ bool isSavePending();
signals:
void configChanged();
@@ -83,7 +87,7 @@ private slots:
*/
void slot_moduleChanged(const QString & module);
- void slot_languageChanged(const QString & language);
+ void slot_languageChanged(int index);
private:
/**
@@ -98,6 +102,8 @@ private:
*/
QString cachedTalkerCodeToTalkerID(const QString& talkerCode);
+ void loadLanguages(const QString & selectedLanguage);
+
/**
* Job ListView.
*/
@@ -107,6 +113,8 @@ private:
* Cache mapping Talker Codes to Talker IDs.
*/
QMap<QString,QString> m_talkerCodesToTalkerIDs;
+
+ bool m_savePending;
};
#endif // KTTSJOBMGR_H
--- a/kttsd/kttsd/kspeech.cpp
+++ b/kttsd/kttsd/kspeech.cpp
@@ -436,6 +436,7 @@ void KSpeech::init()
new KSpeechAdaptor(this);
if (ready()) {
QDBusConnection::sessionBus().registerObject("/KSpeech", this, QDBusConnection::ExportAdaptors);
+ emit kttsdStarted();
}
}
@@ -450,6 +451,7 @@ void KSpeech::reinit()
QDBusConnection::sessionBus().unregisterObject("/KSpeech");
if (ready()) {
QDBusConnection::sessionBus().registerObject("/KSpeech", this, QDBusConnection::ExportAdaptors);
+ emit kttsdStarted();
}
}
@@ -477,7 +479,6 @@ bool KSpeech::ready()
if (!initializeSpeaker())
return false;
announceEvent("ready", "kttsdStarted");
- emit kttsdStarted();
return true;
}
--- a/kttsd/kttsd/speaker.cpp
+++ b/kttsd/kttsd/speaker.cpp
@@ -53,7 +53,7 @@
#include "talkercode.h"
// KTTSD includes.
-//#include "talkermgr.h"
+#include "talkermgr.h"
#include "ssmlconvert.h"
@@ -103,7 +103,8 @@ class SpeakerPrivate
SpeakerPrivate() :
connection(NULL),
filterMgr(NULL),
- config(NULL)
+ config(NULL),
+ currentTalker(QString())
{
if (!ConnectToSpeechd())
kError() << "could not get a connection to speech-dispatcher"<< endl;
@@ -112,6 +113,8 @@ class SpeakerPrivate
filterMgr->init();
config = new KConfig("kttsdrc");
+
+ TalkerMgr::Instance()->loadTalkers(config);
}
~SpeakerPrivate()
@@ -195,6 +198,8 @@ protected:
*/
KConfig *config;
+ QString currentTalker;
+
};
/* Public Methods ==========================================================*/
@@ -256,6 +261,14 @@ void Speaker::init()
delete d->filterMgr;
d->filterMgr = new FilterMgr();
d->filterMgr->init();
+
+ if (d->config) delete d->config;
+ d->config = new KConfig("kttsdrc");
+ TalkerMgr::Instance()->loadTalkers(d->config);
+
+ QString defTalker = TalkerMgr::Instance()->userDefaultTalker();
+ if (!defTalker.isEmpty())
+ activateTalker(defTalker);
}
AppData* Speaker::getAppData(const QString& appId) const
@@ -330,6 +343,13 @@ int Speaker::say(const QString& appId, c
//kDebug() << "Running: Speaker::say appId = " << appId << " text = " << text;
//QString talker = appData->defaultTalker();
+ // Activate another talker if requested
+ if (!appData->defaultTalker().isEmpty() &&
+ appData->defaultTalker() != d->currentTalker)
+ {
+ activateTalker(appData->defaultTalker());
+ }
+
SPDPriority spdpriority = SPD_PROGRESS; // default to least priority
switch (priority)
{
@@ -406,7 +426,7 @@ int Speaker::say(const QString& appId, c
}
//// Note: Set state last so job is fully populated when jobStateChanged signal is emitted.
- appData->jobList()->append(jobNum);
+ //appData->jobList()->append(jobNum);
return jobNum;
}
@@ -449,6 +469,19 @@ bool Speaker::isSpeaking()
return true; // TODO: ask speech-dispatcher somehow?
}
+void Speaker::activateTalker(const QString & talker)
+{
+ TalkerCode tc(talker);
+ setOutputModule(tc.outputModule());
+ setLanguage(tc.language());
+ setVoiceType(tc.voiceType());
+ setSpeed(tc.rate());
+ setPitch(tc.pitch());
+ setVolume(tc.volume());
+
+ d->currentTalker = talker;
+}
+
int Speaker::getCurrentJobNum()
{
return 0;// TODO: ask speech dispatcher if it's needed...
@@ -819,6 +852,9 @@ QStringList Speaker::outputModules()
QStringList Speaker::languagesByModule(const QString & module)
{
+ if (module.isEmpty())
+ return QStringList();
+
QStringList languages;
if (spd_set_output_module(d->connection, module.toUtf8().data()) == 0)
{
@@ -850,12 +886,18 @@ void Speaker::setVolume(int volume)
void Speaker::setOutputModule(const QString & module)
{
+ if (module.isEmpty())
+ return;
+
int result = spd_set_output_module(d->connection, module.toUtf8().data());
// discard result for now, TODO: add error reporting
}
void Speaker::setLanguage(const QString & language)
{
+ if (language.isEmpty())
+ return;
+
int result = spd_set_language(d->connection, language.toUtf8().data());
// discard result for now, TODO: add error reporting
}
--- a/kttsd/kttsd/speaker.h
+++ b/kttsd/kttsd/speaker.h
@@ -380,6 +380,8 @@ public:
void setLanguage(const QString & language);
void setVoiceType(int voiceType);
+ void activateTalker(const QString & talker);
+
signals:
/**
* Emitted when a marker is processed.
--- a/kttsd/kttsd/talkermgr.cpp
+++ b/kttsd/kttsd/talkermgr.cpp
@@ -239,12 +239,7 @@ void TalkerMgr::loadTalkers(KConfig* c)
*/
QStringList TalkerMgr::getTalkers()
{
- QStringList talkerList;
- //for (int ndx = 0; ndx < int(m_loadedPlugIns.count()); ++ndx)
- //{
- // talkerList.append(m_loadedTalkerCodes[ndx].getTalkerCode());
- //}
- return talkerList;
+ return m_loadedTalkerIds;
}
/**
@@ -340,7 +335,8 @@ QString TalkerMgr::talkerCodeToTalkerId(
*/
QString TalkerMgr::userDefaultTalker() const
{
- return m_loadedTalkerCodes[0].getTalkerCode();
+ return (m_loadedTalkerCodes.isEmpty()) ? QString() :
+ m_loadedTalkerCodes[0].getTalkerCode();
}
/**