From 93a1ce76daf94340c8afa9b29a76d116ab37a5df Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Thu, 22 Oct 2020 18:49:56 +0200 Subject: [PATCH] Audio book bugfixing --- PdfTool/pdftoolaudiobook.cpp | 64 ++++++++++++++++++++++++++---------- PdfTool/pdftoolaudiobook.h | 14 ++++---- 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/PdfTool/pdftoolaudiobook.cpp b/PdfTool/pdftoolaudiobook.cpp index b471788..90b7705 100644 --- a/PdfTool/pdftoolaudiobook.cpp +++ b/PdfTool/pdftoolaudiobook.cpp @@ -31,18 +31,34 @@ namespace pdftool static PDFToolAudioBook s_audioBookApplication; static PDFToolAudioBookVoices s_audioBookVoicesApplication; -PDFVoiceInfo::PDFVoiceInfo(std::map properties, ISpVoice* voice) : +PDFVoiceInfo::PDFVoiceInfo(std::map properties, ISpObjectToken* voiceToken) : m_properties(qMove(properties)), - m_voice(voice) + m_voiceToken(voiceToken) { + if (m_voiceToken) + { + m_voiceToken->AddRef(); + } +} +PDFVoiceInfo::PDFVoiceInfo(PDFVoiceInfo&& other) +{ + std::swap(m_properties, other.m_properties); + std::swap(m_voiceToken, other.m_voiceToken); +} + +PDFVoiceInfo& PDFVoiceInfo::operator=(PDFVoiceInfo&& other) +{ + std::swap(m_properties, other.m_properties); + std::swap(m_voiceToken, other.m_voiceToken); + return *this; } PDFVoiceInfo::~PDFVoiceInfo() { - if (m_voice) + if (m_voiceToken) { - m_voice->Release(); + m_voiceToken->Release(); } } @@ -82,7 +98,7 @@ QString PDFVoiceInfo::getStringValue(QString key) const return QString(); } -int PDFToolAudioBookBase::fillVoices(const PDFToolOptions& options, PDFVoiceInfoList& list, bool fillVoicePointers) +int PDFToolAudioBookBase::fillVoices(const PDFToolOptions& options, PDFVoiceInfoList& list, bool fillVoiceTokenPointers) { int result = ExitSuccess; @@ -167,13 +183,14 @@ int PDFToolAudioBookBase::fillVoices(const PDFToolOptions& options, PDFVoiceInfo attributes->Release(); } - ISpVoice* voice = nullptr; - if (fillVoicePointers) + if (fillVoiceTokenPointers) { - token->QueryInterface(__uuidof(ISpVoice), (void**)&voice); + list.emplace_back(qMove(properties), token); + } + else + { + list.emplace_back(qMove(properties), nullptr); } - - list.emplace_back(qMove(properties), voice); token->Release(); } @@ -370,18 +387,18 @@ int PDFToolAudioBook::createAudioBook(const PDFToolOptions& options, pdf::PDFDoc // Do we have any voice? if (voices.empty()) { - PDFConsole::writeError(PDFToolTranslationContext::tr("Invalid voice."), options.outputCodec); + PDFConsole::writeError(PDFToolTranslationContext::tr("No suitable voice found."), options.outputCodec); return ErrorSAPI; } - if (!voices.front().getVoice()) + if (!voices.front().getVoiceToken()) { PDFConsole::writeError(PDFToolTranslationContext::tr("Invalid voice."), options.outputCodec); return ErrorSAPI; } QFileInfo info(options.document); - QString outputFile = QString("%1/%2.mp3").arg(info.path(), info.completeBaseName()); + QString outputFile = QString("%1/%2.wav").arg(info.path(), info.completeBaseName()); BSTR outputFileName = (BSTR)outputFile.utf16(); ISpeechFileStream* stream = nullptr; @@ -390,15 +407,28 @@ int PDFToolAudioBook::createAudioBook(const PDFToolOptions& options, pdf::PDFDoc PDFConsole::writeError(PDFToolTranslationContext::tr("Cannot create output stream '%1'.").arg(outputFile), options.outputCodec); return ErrorSAPI; } - if (!SUCCEEDED(stream->Open(outputFileName, SSFMCreateForWrite))) + + ISpVoice* voice = nullptr; + if (!SUCCEEDED(::CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, __uuidof(ISpVoice), (LPVOID*)&voice))) { - PDFConsole::writeError(PDFToolTranslationContext::tr("Cannot create output stream '%1'.").arg(outputFile), options.outputCodec); + PDFConsole::writeError(PDFToolTranslationContext::tr("Cannot create voice."), options.outputCodec); stream->Release(); return ErrorSAPI; } - ISpVoice* voice = voices.front().getVoice(); - voice->AddRef(); + if (!SUCCEEDED(stream->Open(outputFileName, SSFMCreateForWrite))) + { + PDFConsole::writeError(PDFToolTranslationContext::tr("Cannot create output stream '%1'.").arg(outputFile), options.outputCodec); + voice->Release(); + stream->Release(); + return ErrorSAPI; + } + + ISpObjectToken* voiceToken = voices.front().getVoiceToken(); + if (!SUCCEEDED(voice->SetVoice(voiceToken))) + { + PDFConsole::writeError(PDFToolTranslationContext::tr("Failed to set requested voice. Default voice will be used."), options.outputCodec); + } voices.clear(); LPCWSTR stringToSpeak = (LPCWSTR)audioString.utf16(); diff --git a/PdfTool/pdftoolaudiobook.h b/PdfTool/pdftoolaudiobook.h index b8442ac..a919ea0 100644 --- a/PdfTool/pdftoolaudiobook.h +++ b/PdfTool/pdftoolaudiobook.h @@ -22,7 +22,7 @@ #ifdef Q_OS_WIN -struct ISpVoice; +struct ISpObjectToken; namespace pdf { @@ -36,12 +36,12 @@ class PDFVoiceInfo { public: PDFVoiceInfo() = default; - PDFVoiceInfo(std::map properties, ISpVoice* voice); + PDFVoiceInfo(std::map properties, ISpObjectToken* voiceToken); PDFVoiceInfo(const PDFVoiceInfo&) = delete; - PDFVoiceInfo(PDFVoiceInfo&&) = default; + PDFVoiceInfo(PDFVoiceInfo&& other); PDFVoiceInfo& operator=(const PDFVoiceInfo&) = delete; - PDFVoiceInfo& operator=(PDFVoiceInfo&&) = default; + PDFVoiceInfo& operator=(PDFVoiceInfo&&other); ~PDFVoiceInfo(); @@ -54,11 +54,11 @@ public: QLocale getLocale() const; QString getStringValue(QString key) const; - ISpVoice* getVoice() const { return m_voice; } + ISpObjectToken* getVoiceToken() const { return m_voiceToken; } private: std::map m_properties; - ISpVoice* m_voice = nullptr; + ISpObjectToken* m_voiceToken = nullptr; }; using PDFVoiceInfoList = std::vector; @@ -69,7 +69,7 @@ public: PDFToolAudioBookBase() = default; protected: - int fillVoices(const PDFToolOptions& options, PDFVoiceInfoList& list, bool fillVoicePointers); + int fillVoices(const PDFToolOptions& options, PDFVoiceInfoList& list, bool fillVoiceTokenPointers); int showVoiceList(const PDFToolOptions& options); };