File indexing completed on 2024-05-12 12:43:09

0001 /*
0002    SPDX-FileCopyrightText: 2014-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "texttospeech.h"
0008 #include "texttospeechutil.h"
0009 
0010 #include <KConfig>
0011 #include <KConfigGroup>
0012 #include <QLocale>
0013 #include <QTextToSpeech>
0014 #include <QVector>
0015 
0016 class TextEditTextToSpeech::TextToSpeechPrivate
0017 {
0018 public:
0019     QString mDefaultEngine;
0020     QTextToSpeech *mTextToSpeech = nullptr;
0021 };
0022 
0023 using namespace TextEditTextToSpeech;
0024 TextToSpeech::TextToSpeech(QObject *parent)
0025     : QObject(parent)
0026     , d(new TextEditTextToSpeech::TextToSpeechPrivate)
0027 {
0028     reloadSettings();
0029 }
0030 
0031 TextToSpeech::~TextToSpeech() = default;
0032 
0033 void TextToSpeech::reloadSettings()
0034 {
0035     const TextEditTextToSpeech::TextToSpeechUtil::TextToSpeechSettings settings = TextEditTextToSpeech::TextToSpeechUtil::loadSettings();
0036 
0037     const QString engineName = settings.engineName;
0038     if (d->mDefaultEngine != engineName) {
0039         if (d->mTextToSpeech) {
0040 #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
0041             if (d->mTextToSpeech && (d->mTextToSpeech->engine() != engineName))
0042 #endif
0043             {
0044                 disconnect(d->mTextToSpeech, &QTextToSpeech::stateChanged, this, &TextToSpeech::slotStateChanged);
0045                 delete d->mTextToSpeech;
0046                 d->mTextToSpeech = nullptr;
0047             }
0048         }
0049     }
0050     if (!d->mTextToSpeech) {
0051         d->mTextToSpeech = new QTextToSpeech(engineName, this);
0052         connect(d->mTextToSpeech, &QTextToSpeech::stateChanged, this, &TextToSpeech::slotStateChanged);
0053     }
0054     d->mDefaultEngine = engineName;
0055     const int rate = settings.rate;
0056     const double rateDouble = rate / 100.0;
0057     d->mTextToSpeech->setRate(rateDouble);
0058     const int pitch = settings.pitch;
0059     const double pitchDouble = pitch / 100.0;
0060     d->mTextToSpeech->setPitch(pitchDouble);
0061     const int volumeValue = settings.volumeValue;
0062     const double volumeDouble = volumeValue / 100.0;
0063     d->mTextToSpeech->setVolume(volumeDouble);
0064     d->mTextToSpeech->setLocale(QLocale(settings.localeName));
0065     // It doesn't have api for it d->mTextToSpeech->setVoice(grp.readEntry("voice"));
0066 }
0067 
0068 TextToSpeech *TextToSpeech::self()
0069 {
0070     static TextToSpeech s_self;
0071     return &s_self;
0072 }
0073 
0074 void TextToSpeech::slotStateChanged()
0075 {
0076     TextToSpeech::State state;
0077     switch (d->mTextToSpeech->state()) {
0078     case QTextToSpeech::Ready:
0079         state = TextToSpeech::Ready;
0080         break;
0081     case QTextToSpeech::Speaking:
0082         state = TextToSpeech::Speaking;
0083         break;
0084     case QTextToSpeech::Paused:
0085         state = TextToSpeech::Paused;
0086         break;
0087 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0088     case QTextToSpeech::BackendError:
0089         state = TextToSpeech::BackendError;
0090 #else
0091     case QTextToSpeech::Error:
0092         state = TextToSpeech::BackendError;
0093         break;
0094     case QTextToSpeech::Synthesizing:
0095         state = TextToSpeech::Synthesizing;
0096         break;
0097 #endif
0098     }
0099     Q_EMIT stateChanged(state);
0100 }
0101 
0102 bool TextToSpeech::isReady() const
0103 {
0104 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0105     return d->mTextToSpeech->state() != QTextToSpeech::BackendError;
0106 #else
0107     return d->mTextToSpeech->state() != QTextToSpeech::Error;
0108 #endif
0109 }
0110 
0111 void TextToSpeech::say(const QString &text)
0112 {
0113     d->mTextToSpeech->say(text);
0114 }
0115 
0116 void TextToSpeech::stop()
0117 {
0118     d->mTextToSpeech->stop();
0119 }
0120 
0121 void TextToSpeech::pause()
0122 {
0123     d->mTextToSpeech->pause();
0124 }
0125 
0126 void TextToSpeech::resume()
0127 {
0128     d->mTextToSpeech->resume();
0129 }
0130 
0131 void TextToSpeech::setRate(double rate)
0132 {
0133     d->mTextToSpeech->setRate(rate);
0134 }
0135 
0136 void TextToSpeech::setPitch(double pitch)
0137 {
0138     d->mTextToSpeech->setPitch(pitch);
0139 }
0140 
0141 void TextToSpeech::setVolume(double volume)
0142 {
0143     d->mTextToSpeech->setVolume(volume);
0144 }
0145 
0146 double TextToSpeech::volume() const
0147 {
0148     return d->mTextToSpeech->volume();
0149 }
0150 
0151 QVector<QLocale> TextToSpeech::availableLocales() const
0152 {
0153     return d->mTextToSpeech->availableLocales();
0154 }
0155 
0156 QStringList TextToSpeech::availableVoices() const
0157 {
0158     QStringList lst;
0159     const QVector<QVoice> voices = d->mTextToSpeech->availableVoices();
0160     lst.reserve(voices.count());
0161     for (const QVoice &voice : voices) {
0162         lst << voice.name();
0163     }
0164     return lst;
0165 }
0166 
0167 QStringList TextToSpeech::availableEngines() const
0168 {
0169     return QTextToSpeech::availableEngines();
0170 }
0171 
0172 void TextToSpeech::setLocale(const QLocale &locale) const
0173 {
0174     d->mTextToSpeech->setLocale(locale);
0175 }
0176 
0177 QLocale TextToSpeech::locale() const
0178 {
0179     return d->mTextToSpeech->locale();
0180 }
0181 
0182 #include "moc_texttospeech.cpp"