mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-02-20 21:50:38 +01:00
Voice info application
This commit is contained in:
parent
e5e37b3283
commit
e9ae0595e3
@ -217,6 +217,14 @@ void PDFToolAbstractApplication::initializeCommandLineParser(QCommandLineParser*
|
|||||||
parser->addOption(QCommandLineOption("text-show-struct-act-text", "Show actual text extracted from structure tree."));
|
parser->addOption(QCommandLineOption("text-show-struct-act-text", "Show actual text extracted from structure tree."));
|
||||||
parser->addOption(QCommandLineOption("text-show-phoneme", "Show phoneme extracted from structure tree."));
|
parser->addOption(QCommandLineOption("text-show-phoneme", "Show phoneme extracted from structure tree."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (optionFlags.testFlag(VoiceSelector))
|
||||||
|
{
|
||||||
|
parser->addOption(QCommandLineOption("voice-name", "Choose voice name for text-to-speech engine.", "name"));
|
||||||
|
parser->addOption(QCommandLineOption("voice-gender", "Choose voice gender for text-to-speech engine.", "gender"));
|
||||||
|
parser->addOption(QCommandLineOption("voice-age", "Choose voice age for text-to-speech engine.", "age"));
|
||||||
|
parser->addOption(QCommandLineOption("voice-lang-code", "Choose voice language code for text-to-speech engine.", "code"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser) const
|
PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser) const
|
||||||
@ -360,6 +368,14 @@ PDFToolOptions PDFToolAbstractApplication::getOptions(QCommandLineParser* parser
|
|||||||
options.textShowStructPhoneme = parser->isSet("text-show-phoneme");
|
options.textShowStructPhoneme = parser->isSet("text-show-phoneme");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (optionFlags.testFlag(VoiceSelector))
|
||||||
|
{
|
||||||
|
options.textVoiceName = parser->isSet("voice-name") ? parser->value("voice-name") : QString();
|
||||||
|
options.textVoiceGender = parser->isSet("voice-gender") ? parser->value("voice-gender") : QString();
|
||||||
|
options.textVoiceAge = parser->isSet("voice-age") ? parser->value("voice-age") : QString();
|
||||||
|
options.textVoiceLangCode = parser->isSet("voice-lang-code") ? parser->value("voice-lang-code") : QString();
|
||||||
|
}
|
||||||
|
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +93,22 @@ struct PDFToolOptions
|
|||||||
bool textShowStructActualText = false;
|
bool textShowStructActualText = false;
|
||||||
bool textShowStructPhoneme = false;
|
bool textShowStructPhoneme = false;
|
||||||
|
|
||||||
|
// For option 'VoiceSelector'
|
||||||
|
QString textVoiceName;
|
||||||
|
QString textVoiceGender;
|
||||||
|
QString textVoiceAge;
|
||||||
|
QString textVoiceLangCode;
|
||||||
|
|
||||||
|
// For option 'TextSpeech'
|
||||||
|
bool textSpeechMarkPageNumbers = false;
|
||||||
|
bool textSpeechSayPageNumbers = false;
|
||||||
|
bool textSpeechSayStructTitles = false;
|
||||||
|
bool textSpeechSayStructLanguage = false;
|
||||||
|
bool textSpeechSayStructAlternativeDescription = false;
|
||||||
|
bool textSpeechSayStructExpandedForm = false;
|
||||||
|
bool textSpeechSayStructActualText = false;
|
||||||
|
bool textSpeechSayStructPhoneme = false;
|
||||||
|
|
||||||
/// Returns page range. If page range is invalid, then \p errorMessage is empty.
|
/// Returns page range. If page range is invalid, then \p errorMessage is empty.
|
||||||
/// \param pageCount Page count
|
/// \param pageCount Page count
|
||||||
/// \param[out] errorMessage Error message
|
/// \param[out] errorMessage Error message
|
||||||
@ -139,6 +155,8 @@ public:
|
|||||||
PageSelector = 0x0080, ///< Select page range (or all pages)
|
PageSelector = 0x0080, ///< Select page range (or all pages)
|
||||||
TextAnalysis = 0x0100, ///< Text analysis options
|
TextAnalysis = 0x0100, ///< Text analysis options
|
||||||
TextShow = 0x0200, ///< Text extract and show options
|
TextShow = 0x0200, ///< Text extract and show options
|
||||||
|
VoiceSelector = 0x0400, ///< Select voice from SAPI
|
||||||
|
TextSpeech = 0x0800, ///< Text speech options
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Options, Option)
|
Q_DECLARE_FLAGS(Options, Option)
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ namespace pdftool
|
|||||||
{
|
{
|
||||||
|
|
||||||
static PDFToolAudioBook s_audioBookApplication;
|
static PDFToolAudioBook s_audioBookApplication;
|
||||||
|
static PDFToolAudioBookVoices s_audioBookVoicesApplication;
|
||||||
|
|
||||||
PDFVoiceInfo::PDFVoiceInfo(std::map<QString, QString> properties, ISpVoice* voice) :
|
PDFVoiceInfo::PDFVoiceInfo(std::map<QString, QString> properties, ISpVoice* voice) :
|
||||||
m_properties(qMove(properties)),
|
m_properties(qMove(properties)),
|
||||||
@ -51,11 +52,19 @@ QLocale PDFVoiceInfo::getLocale() const
|
|||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
{
|
{
|
||||||
|
// Language name
|
||||||
int count = GetLocaleInfoW(locale, LOCALE_SISO639LANGNAME, NULL, 0);
|
int count = GetLocaleInfoW(locale, LOCALE_SISO639LANGNAME, NULL, 0);
|
||||||
std::vector<wchar_t> localeString(count, wchar_t());
|
std::vector<wchar_t> buffer(count, wchar_t());
|
||||||
GetLocaleInfoW(locale, LOCALE_SISO639LANGNAME, localeString.data(), int(localeString.size()));
|
GetLocaleInfoW(locale, LOCALE_SISO639LANGNAME, buffer.data(), int(buffer.size()));
|
||||||
QString isoCode = QString::fromWCharArray(localeString.data());
|
QString languageCode = QString::fromWCharArray(buffer.data());
|
||||||
return QLocale(isoCode);
|
|
||||||
|
// Country name
|
||||||
|
count = GetLocaleInfoW(locale, LOCALE_SISO3166CTRYNAME, NULL, 0);
|
||||||
|
buffer.resize(count, wchar_t());
|
||||||
|
GetLocaleInfoW(locale, LOCALE_SISO3166CTRYNAME, buffer.data(), int(buffer.size()));
|
||||||
|
QString countryCode = QString::fromWCharArray(buffer.data());
|
||||||
|
|
||||||
|
return QLocale(QString("%1_%2").arg(languageCode, countryCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
return QLocale();
|
return QLocale();
|
||||||
@ -72,50 +81,30 @@ QString PDFVoiceInfo::getStringValue(QString key) const
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PDFToolAudioBook::getStandardString(StandardString standardString) const
|
int PDFToolAudioBookBase::fillVoices(const PDFToolOptions& options, PDFVoiceInfoList& list, bool fillVoicePointers)
|
||||||
{
|
|
||||||
switch (standardString)
|
|
||||||
{
|
|
||||||
case Command:
|
|
||||||
return "audio-book";
|
|
||||||
|
|
||||||
case Name:
|
|
||||||
return PDFToolTranslationContext::tr("Audio book convertor");
|
|
||||||
|
|
||||||
case Description:
|
|
||||||
return PDFToolTranslationContext::tr("Convert your document to a simple audio book.");
|
|
||||||
|
|
||||||
default:
|
|
||||||
Q_ASSERT(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
|
|
||||||
int PDFToolAudioBook::execute(const PDFToolOptions& options)
|
|
||||||
{
|
|
||||||
if (!SUCCEEDED(::CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_SPEED_OVER_MEMORY)))
|
|
||||||
{
|
|
||||||
return ErrorCOM;
|
|
||||||
}
|
|
||||||
|
|
||||||
int returnCode = showVoiceList(options);
|
|
||||||
|
|
||||||
::CoUninitialize();
|
|
||||||
|
|
||||||
return returnCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
PDFToolAbstractApplication::Options PDFToolAudioBook::getOptionsFlags() const
|
|
||||||
{
|
|
||||||
return ConsoleFormat | OpenDocument | PageSelector | TextAnalysis;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PDFToolAudioBook::fillVoices(const PDFToolOptions& options, PDFVoiceInfoList& list, bool fillVoicePointers)
|
|
||||||
{
|
{
|
||||||
int result = ExitSuccess;
|
int result = ExitSuccess;
|
||||||
|
|
||||||
|
QStringList voiceSelector;
|
||||||
|
if (!options.textVoiceName.isEmpty())
|
||||||
|
{
|
||||||
|
voiceSelector << QString("Name=%1").arg(options.textVoiceName);
|
||||||
|
}
|
||||||
|
if (!options.textVoiceGender.isEmpty())
|
||||||
|
{
|
||||||
|
voiceSelector << QString("Gender=%1").arg(options.textVoiceGender);
|
||||||
|
}
|
||||||
|
if (!options.textVoiceAge.isEmpty())
|
||||||
|
{
|
||||||
|
voiceSelector << QString("Age=%1").arg(options.textVoiceAge);
|
||||||
|
}
|
||||||
|
if (!options.textVoiceLangCode.isEmpty())
|
||||||
|
{
|
||||||
|
voiceSelector << QString("Language=%1").arg(options.textVoiceLangCode);
|
||||||
|
}
|
||||||
|
QString voiceSelectorString = voiceSelector.join(";");
|
||||||
|
LPCWSTR requiredAttributes = !voiceSelectorString.isEmpty() ? (LPCWSTR)voiceSelectorString.utf16() : nullptr;
|
||||||
|
|
||||||
ISpObjectTokenCategory* category = nullptr;
|
ISpObjectTokenCategory* category = nullptr;
|
||||||
if (!SUCCEEDED(::CoCreateInstance(CLSID_SpObjectTokenCategory, NULL, CLSCTX_ALL, __uuidof(ISpObjectTokenCategory), (LPVOID*)&category)))
|
if (!SUCCEEDED(::CoCreateInstance(CLSID_SpObjectTokenCategory, NULL, CLSCTX_ALL, __uuidof(ISpObjectTokenCategory), (LPVOID*)&category)))
|
||||||
{
|
{
|
||||||
@ -130,7 +119,7 @@ int PDFToolAudioBook::fillVoices(const PDFToolOptions& options, PDFVoiceInfoList
|
|||||||
}
|
}
|
||||||
|
|
||||||
IEnumSpObjectTokens* enumTokensObject = nullptr;
|
IEnumSpObjectTokens* enumTokensObject = nullptr;
|
||||||
if (SUCCEEDED(category->EnumTokens(NULL, NULL, &enumTokensObject)))
|
if (SUCCEEDED(category->EnumTokens(requiredAttributes, NULL, &enumTokensObject)))
|
||||||
{
|
{
|
||||||
ISpObjectToken* token = nullptr;
|
ISpObjectToken* token = nullptr;
|
||||||
while (SUCCEEDED(enumTokensObject->Next(1, &token, NULL)))
|
while (SUCCEEDED(enumTokensObject->Next(1, &token, NULL)))
|
||||||
@ -212,7 +201,7 @@ int PDFToolAudioBook::fillVoices(const PDFToolOptions& options, PDFVoiceInfoList
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PDFToolAudioBook::showVoiceList(const PDFToolOptions& options)
|
int PDFToolAudioBookBase::showVoiceList(const PDFToolOptions& options)
|
||||||
{
|
{
|
||||||
PDFVoiceInfoList voices;
|
PDFVoiceInfoList voices;
|
||||||
int result = fillVoices(options, voices, false);
|
int result = fillVoices(options, voices, false);
|
||||||
@ -227,22 +216,27 @@ int PDFToolAudioBook::showVoiceList(const PDFToolOptions& options)
|
|||||||
formatter.writeTableHeaderColumn("name", PDFToolTranslationContext::tr("Name"), Qt::AlignLeft);
|
formatter.writeTableHeaderColumn("name", PDFToolTranslationContext::tr("Name"), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("gender", PDFToolTranslationContext::tr("Gender"), Qt::AlignLeft);
|
formatter.writeTableHeaderColumn("gender", PDFToolTranslationContext::tr("Gender"), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("age", PDFToolTranslationContext::tr("Age"), Qt::AlignLeft);
|
formatter.writeTableHeaderColumn("age", PDFToolTranslationContext::tr("Age"), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("language", PDFToolTranslationContext::tr("Language"), Qt::AlignLeft);
|
formatter.writeTableHeaderColumn("language-code", PDFToolTranslationContext::tr("Lang. Code"), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("locale", PDFToolTranslationContext::tr("Locale"), Qt::AlignLeft);
|
formatter.writeTableHeaderColumn("locale", PDFToolTranslationContext::tr("Locale"), Qt::AlignLeft);
|
||||||
|
formatter.writeTableHeaderColumn("language", PDFToolTranslationContext::tr("Language"), Qt::AlignLeft);
|
||||||
|
formatter.writeTableHeaderColumn("country", PDFToolTranslationContext::tr("Country"), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("vendor", PDFToolTranslationContext::tr("Vendor"), Qt::AlignLeft);
|
formatter.writeTableHeaderColumn("vendor", PDFToolTranslationContext::tr("Vendor"), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("version", PDFToolTranslationContext::tr("Version"), Qt::AlignLeft);
|
formatter.writeTableHeaderColumn("version", PDFToolTranslationContext::tr("Version"), Qt::AlignLeft);
|
||||||
formatter.endTableHeaderRow();
|
formatter.endTableHeaderRow();
|
||||||
|
|
||||||
for (const PDFVoiceInfo& voice : voices)
|
for (const PDFVoiceInfo& voice : voices)
|
||||||
{
|
{
|
||||||
|
QLocale locale = voice.getLocale();
|
||||||
formatter.beginTableRow("voice");
|
formatter.beginTableRow("voice");
|
||||||
formatter.writeTableHeaderColumn("name", voice.getName(), Qt::AlignLeft);
|
formatter.writeTableColumn("name", voice.getName(), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("gender", voice.getGender(), Qt::AlignLeft);
|
formatter.writeTableColumn("gender", voice.getGender(), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("age", voice.getAge(), Qt::AlignLeft);
|
formatter.writeTableColumn("age", voice.getAge(), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("language", voice.getLanguage(), Qt::AlignLeft);
|
formatter.writeTableColumn("language", voice.getLanguage(), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("locale", voice.getLocale().name(), Qt::AlignLeft);
|
formatter.writeTableColumn("locale", locale.name(), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("vendor", voice.getVendor(), Qt::AlignLeft);
|
formatter.writeTableColumn("language", locale.nativeLanguageName(), Qt::AlignLeft);
|
||||||
formatter.writeTableHeaderColumn("version", voice.getVersion(), Qt::AlignLeft);
|
formatter.writeTableColumn("country", locale.nativeCountryName(), Qt::AlignLeft);
|
||||||
|
formatter.writeTableColumn("vendor", voice.getVendor(), Qt::AlignLeft);
|
||||||
|
formatter.writeTableColumn("version", voice.getVersion(), Qt::AlignLeft);
|
||||||
formatter.endTableRow();
|
formatter.endTableRow();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,6 +248,84 @@ int PDFToolAudioBook::showVoiceList(const PDFToolOptions& options)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString PDFToolAudioBookVoices::getStandardString(PDFToolAbstractApplication::StandardString standardString) const
|
||||||
|
{
|
||||||
|
switch (standardString)
|
||||||
|
{
|
||||||
|
case Command:
|
||||||
|
return "audio-book-voices";
|
||||||
|
|
||||||
|
case Name:
|
||||||
|
return PDFToolTranslationContext::tr("Audio book voices");
|
||||||
|
|
||||||
|
case Description:
|
||||||
|
return PDFToolTranslationContext::tr("List of available voices for audio book conversion.");
|
||||||
|
|
||||||
|
default:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int PDFToolAudioBookVoices::execute(const PDFToolOptions& options)
|
||||||
|
{
|
||||||
|
if (!SUCCEEDED(::CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_SPEED_OVER_MEMORY)))
|
||||||
|
{
|
||||||
|
return ErrorCOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
int returnCode = showVoiceList(options);
|
||||||
|
|
||||||
|
::CoUninitialize();
|
||||||
|
|
||||||
|
return returnCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFToolAbstractApplication::Options PDFToolAudioBookVoices::getOptionsFlags() const
|
||||||
|
{
|
||||||
|
return ConsoleFormat | VoiceSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PDFToolAudioBook::getStandardString(StandardString standardString) const
|
||||||
|
{
|
||||||
|
switch (standardString)
|
||||||
|
{
|
||||||
|
case Command:
|
||||||
|
return "audio-book";
|
||||||
|
|
||||||
|
case Name:
|
||||||
|
return PDFToolTranslationContext::tr("Audio book convertor");
|
||||||
|
|
||||||
|
case Description:
|
||||||
|
return PDFToolTranslationContext::tr("Convert your document to a simple audio book.");
|
||||||
|
|
||||||
|
default:
|
||||||
|
Q_ASSERT(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int PDFToolAudioBook::execute(const PDFToolOptions& options)
|
||||||
|
{
|
||||||
|
if (!SUCCEEDED(::CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_SPEED_OVER_MEMORY)))
|
||||||
|
{
|
||||||
|
return ErrorCOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
::CoUninitialize();
|
||||||
|
|
||||||
|
return ExitSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFToolAbstractApplication::Options PDFToolAudioBook::getOptionsFlags() const
|
||||||
|
{
|
||||||
|
return ConsoleFormat | OpenDocument | PageSelector | VoiceSelector | TextAnalysis;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace pdftool
|
} // namespace pdftool
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -58,16 +58,30 @@ private:
|
|||||||
|
|
||||||
using PDFVoiceInfoList = std::vector<PDFVoiceInfo>;
|
using PDFVoiceInfoList = std::vector<PDFVoiceInfo>;
|
||||||
|
|
||||||
class PDFToolAudioBook : public PDFToolAbstractApplication
|
class PDFToolAudioBookBase : public PDFToolAbstractApplication
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PDFToolAudioBookBase() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int fillVoices(const PDFToolOptions& options, PDFVoiceInfoList& list, bool fillVoicePointers);
|
||||||
|
int showVoiceList(const PDFToolOptions& options);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PDFToolAudioBookVoices : public PDFToolAudioBookBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual QString getStandardString(StandardString standardString) const override;
|
virtual QString getStandardString(StandardString standardString) const override;
|
||||||
virtual int execute(const PDFToolOptions& options) override;
|
virtual int execute(const PDFToolOptions& options) override;
|
||||||
virtual Options getOptionsFlags() const override;
|
virtual Options getOptionsFlags() const override;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
class PDFToolAudioBook : public PDFToolAudioBookBase
|
||||||
int fillVoices(const PDFToolOptions& options, PDFVoiceInfoList& list, bool fillVoicePointers);
|
{
|
||||||
int showVoiceList(const PDFToolOptions& options);
|
public:
|
||||||
|
virtual QString getStandardString(StandardString standardString) const override;
|
||||||
|
virtual int execute(const PDFToolOptions& options) override;
|
||||||
|
virtual Options getOptionsFlags() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pdftool
|
} // namespace pdftool
|
||||||
|
Loading…
x
Reference in New Issue
Block a user