File indexing completed on 2024-05-19 04:35:47
0001 /* 0002 SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "tts.h" 0008 0009 #include <QSet> 0010 0011 #include <KLocalizedString> 0012 0013 #include "settings.h" 0014 0015 /* Private storage. */ 0016 class OkularTTS::Private 0017 { 0018 public: 0019 explicit Private(OkularTTS *qq) 0020 : q(qq) 0021 , speech(new QTextToSpeech(Okular::Settings::ttsEngine())) 0022 { 0023 const QVector<QVoice> voices = speech->availableVoices(); 0024 QString voiceName = Okular::Settings::ttsVoice(); 0025 for (const QVoice &voice : voices) { 0026 if (voice.name() == voiceName) { 0027 speech->setVoice(voice); 0028 } 0029 } 0030 } 0031 0032 ~Private() 0033 { 0034 delete speech; 0035 speech = nullptr; 0036 } 0037 0038 OkularTTS *q; 0039 QTextToSpeech *speech; 0040 // Which speech engine was used when above object was created. 0041 // When the setting changes, we need to stop speaking and recreate. 0042 QString speechEngine; 0043 Q_DISABLE_COPY(Private) 0044 }; 0045 0046 OkularTTS::OkularTTS(QObject *parent) 0047 : QObject(parent) 0048 , d(new Private(this)) 0049 { 0050 // Initialize speechEngine so we can reinitialize if it changes. 0051 d->speechEngine = Okular::Settings::ttsEngine(); 0052 connect(d->speech, &QTextToSpeech::stateChanged, this, &OkularTTS::slotSpeechStateChanged); 0053 connect(Okular::Settings::self(), &KCoreConfigSkeleton::configChanged, this, &OkularTTS::slotConfigChanged); 0054 } 0055 0056 OkularTTS::~OkularTTS() 0057 { 0058 delete d; 0059 } 0060 0061 void OkularTTS::say(const QString &text) 0062 { 0063 if (text.isEmpty()) { 0064 return; 0065 } 0066 0067 d->speech->say(text); 0068 } 0069 0070 void OkularTTS::stopAllSpeechs() 0071 { 0072 if (!d->speech) { 0073 return; 0074 } 0075 0076 d->speech->stop(); 0077 } 0078 0079 void OkularTTS::pauseResumeSpeech() 0080 { 0081 if (!d->speech) { 0082 return; 0083 } 0084 0085 if (d->speech->state() == QTextToSpeech::Speaking) { 0086 d->speech->pause(); 0087 } else { 0088 d->speech->resume(); 0089 } 0090 } 0091 0092 void OkularTTS::slotSpeechStateChanged(QTextToSpeech::State state) 0093 { 0094 if (state == QTextToSpeech::Speaking) { 0095 Q_EMIT isSpeaking(true); 0096 Q_EMIT canPauseOrResume(true); 0097 } else { 0098 Q_EMIT isSpeaking(false); 0099 if (state == QTextToSpeech::Paused) { 0100 Q_EMIT canPauseOrResume(true); 0101 } else { 0102 Q_EMIT canPauseOrResume(false); 0103 } 0104 } 0105 } 0106 0107 void OkularTTS::slotConfigChanged() 0108 { 0109 const QString engine = Okular::Settings::ttsEngine(); 0110 const QString voiceName = Okular::Settings::ttsVoice(); 0111 if (engine != d->speechEngine) { 0112 d->speech->stop(); 0113 delete d->speech; 0114 d->speech = new QTextToSpeech(engine); 0115 connect(d->speech, &QTextToSpeech::stateChanged, this, &OkularTTS::slotSpeechStateChanged); 0116 d->speechEngine = engine; 0117 } 0118 0119 const QVector<QVoice> voices = d->speech->availableVoices(); 0120 for (const QVoice &voice : voices) { 0121 if (voice.name() == voiceName) { 0122 d->speech->setVoice(voice); 0123 break; 0124 } 0125 } 0126 }