summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaurice Kalinowski <maurice.kalinowski@theqtcompany.com>2015-11-26 14:03:29 +0100
committerMaurice Kalinowski <maurice.kalinowski@theqtcompany.com>2015-12-15 15:44:49 +0000
commit631486c60b0ebe481a39c10216d7a6461e4dad4a (patch)
tree99ae8791a1bba0e58e1bd2c16e3aecbcaec2da1c
parentac67f361b17e9f5fd11b68913842bb508af3bdf0 (diff)
Add WinRT backend using Windows.Media.SpeechSynthesis
Change-Id: Iae50a690bd236ccbc5fb53cb9b96eb0a3252022f Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com> Reviewed-by: Jeremy Whiting <jpwhiting@kde.org>
-rw-r--r--src/plugins/tts/tts.pro1
-rw-r--r--src/plugins/tts/winrt/qtexttospeech_winrt.cpp448
-rw-r--r--src/plugins/tts/winrt/qtexttospeech_winrt.h103
-rw-r--r--src/plugins/tts/winrt/qtexttospeech_winrt_plugin.cpp44
-rw-r--r--src/plugins/tts/winrt/qtexttospeech_winrt_plugin.h63
-rw-r--r--src/plugins/tts/winrt/winrt.pro18
-rw-r--r--src/plugins/tts/winrt/winrt_plugin.json6
7 files changed, 683 insertions, 0 deletions
diff --git a/src/plugins/tts/tts.pro b/src/plugins/tts/tts.pro
index 074e82a..e5b290d 100644
--- a/src/plugins/tts/tts.pro
+++ b/src/plugins/tts/tts.pro
@@ -10,6 +10,7 @@ unix {
# mingw needs copies of the structures defined in sapi.h
# until those are written, disable the sapi plugin for mingw
windows:!winrt:!mingw: SUBDIRS += sapi
+winrt: SUBDIRS += winrt
osx: SUBDIRS += osx
diff --git a/src/plugins/tts/winrt/qtexttospeech_winrt.cpp b/src/plugins/tts/winrt/qtexttospeech_winrt.cpp
new file mode 100644
index 0000000..583cb6f
--- /dev/null
+++ b/src/plugins/tts/winrt/qtexttospeech_winrt.cpp
@@ -0,0 +1,448 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Speech module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtexttospeech_winrt.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/QMap>
+#include <QtCore/QTimer>
+#include <private/qeventdispatcher_winrt_p.h>
+
+#include <windows.foundation.h>
+#include <windows.foundation.collections.h>
+#include <windows.media.speechsynthesis.h>
+#include <windows.storage.streams.h>
+#include <windows.ui.xaml.h>
+#include <windows.ui.xaml.controls.h>
+#include <windows.ui.xaml.markup.h>
+
+#include <functional>
+#include <wrl.h>
+
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::Media::SpeechSynthesis;
+using namespace ABI::Windows::Storage::Streams;
+using namespace ABI::Windows::UI::Xaml;
+using namespace ABI::Windows::UI::Xaml::Controls;
+using namespace ABI::Windows::UI::Xaml::Markup;
+using namespace ABI::Windows::UI::Xaml::Media;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+QT_BEGIN_NAMESPACE
+
+#define LSTRING(str) L#str
+static const wchar_t webviewXaml[] = LSTRING(
+<MediaElement xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
+);
+
+class QTextToSpeechEngineWinRTPrivate
+{
+public:
+ QTimer timer;
+ ComPtr<IXamlReaderStatics> xamlReader;
+ ComPtr<ISpeechSynthesizer> synth;
+ QVector<QLocale> locales;
+ QVector<QVoice> voices;
+ QVector<ComPtr<IVoiceInformation>> infos;
+ EventRegistrationToken tok;
+
+ ComPtr<IMediaElement> media;
+
+ double rate;
+ double volume;
+
+ QTextToSpeech::State state;
+};
+
+QTextToSpeechEngineWinRT::QTextToSpeechEngineWinRT(const QVariantMap &, QObject *parent)
+ : QTextToSpeechEngine(parent)
+ , d_ptr(new QTextToSpeechEngineWinRTPrivate)
+{
+ d_ptr->rate = 0;
+ d_ptr->volume = 100;
+ d_ptr->timer.setInterval(100);
+ connect(&d_ptr->timer, &QTimer::timeout, this, &QTextToSpeechEngineWinRT::checkElementState);
+
+ init();
+}
+
+QTextToSpeechEngineWinRT::~QTextToSpeechEngineWinRT()
+{
+}
+
+QVector<QLocale> QTextToSpeechEngineWinRT::availableLocales() const
+{
+ Q_D(const QTextToSpeechEngineWinRT);
+ return d->locales;
+}
+
+QVector<QVoice> QTextToSpeechEngineWinRT::availableVoices() const
+{
+ Q_D(const QTextToSpeechEngineWinRT);
+ return d->voices;
+}
+
+void QTextToSpeechEngineWinRT::say(const QString &text)
+{
+ Q_D(QTextToSpeechEngineWinRT);
+
+ HRESULT hr;
+
+ hr = QEventDispatcherWinRT::runOnXamlThread([text, d]() {
+ HRESULT hr;
+ HStringReference nativeText(reinterpret_cast<LPCWSTR>(text.utf16()), text.length());
+ ComPtr<IAsyncOperation<SpeechSynthesisStream*>> op;
+
+ hr = d->synth->SynthesizeTextToStreamAsync(nativeText.Get(), &op);
+ RETURN_HR_IF_FAILED("Could not synthesize text.");
+
+ ComPtr<ISpeechSynthesisStream> stream;
+ hr = QWinRTFunctions::await(op, stream.GetAddressOf());
+ RETURN_HR_IF_FAILED("Synthesizing failed.");
+
+ ComPtr<IRandomAccessStream> randomStream;
+ hr = stream.As(&randomStream);
+ RETURN_HR_IF_FAILED("Could not cast to RandomAccessStream.");
+
+ // Directly instantiating a MediaElement works, but it throws an exception
+ // when setting the source. Using a XamlReader appears to set it up properly.
+ ComPtr<IInspectable> element;
+ hr = d->xamlReader->Load(HString::MakeReference(webviewXaml).Get(), &element);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ if (d->media)
+ d->media.Reset();
+
+ hr = element.As(&d->media);
+ RETURN_HR_IF_FAILED("Could not create MediaElement for playback.");
+
+ // Volume and Playback Rate cannot be changed for synthesized audio once
+ // it has been created. Hence QTextToSpeechEngineWinRT::setVolume/Rate
+ // only cache the value until playback is started.
+ hr = d->media->put_DefaultPlaybackRate(d->rate + 1);
+ if (FAILED(hr))
+ qWarning("Could not set playback rate.");
+
+ const DOUBLE vol = DOUBLE(d->volume) / 100.;
+ hr = d->media->put_Volume(vol);
+ if (FAILED(hr))
+ qWarning("Could not set volume.");
+
+ static const HStringReference empty(L"");
+ hr = d->media->SetSource(randomStream.Get(), empty.Get());
+ RETURN_HR_IF_FAILED("Could not set media source.");
+
+ hr = d->media->Play();
+ RETURN_HR_IF_FAILED("Could not initiate playback.");
+
+ return S_OK;
+ });
+ if (SUCCEEDED(hr)) {
+ d->timer.start();
+ d->state = QTextToSpeech::Speaking;
+ } else {
+ d->state = QTextToSpeech::BackendError;
+ }
+ emit stateChanged(d->state);
+}
+
+void QTextToSpeechEngineWinRT::stop()
+{
+ Q_D(QTextToSpeechEngineWinRT);
+
+ if (!d->media)
+ return;
+
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
+ HRESULT hr = d->media->Stop();
+ RETURN_HR_IF_FAILED("Could not stop playback.");
+
+ d->media.Reset();
+ return hr;
+ });
+ if (SUCCEEDED(hr)) {
+ d->timer.stop();
+ d->state = QTextToSpeech::Ready;
+ emit stateChanged(d->state);
+ }
+}
+
+void QTextToSpeechEngineWinRT::pause()
+{
+ Q_D(QTextToSpeechEngineWinRT);
+
+ if (!d->media)
+ return;
+
+ // Stop timer first to not have checkElementState being invoked
+ // while context switch to/from Xaml thread happens.
+ d->timer.stop();
+
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
+ HRESULT hr = d->media->Pause();
+ RETURN_HR_IF_FAILED("Could not pause playback.");
+ return hr;
+ });
+ if (SUCCEEDED(hr)) {
+ d->state = QTextToSpeech::Paused;
+ emit stateChanged(d->state);
+ }
+}
+
+void QTextToSpeechEngineWinRT::resume()
+{
+ Q_D(QTextToSpeechEngineWinRT);
+
+ if (!d->media)
+ return;
+
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
+ HRESULT hr = d->media->Play();
+ RETURN_HR_IF_FAILED("Could not resume playback.");
+ return hr;
+ });
+ if (SUCCEEDED(hr)) {
+ d->timer.start();
+ d->state = QTextToSpeech::Speaking;
+ emit stateChanged(d->state);
+ }
+}
+
+double QTextToSpeechEngineWinRT::rate() const
+{
+ Q_D(const QTextToSpeechEngineWinRT);
+
+ return d->rate;
+}
+
+bool QTextToSpeechEngineWinRT::setRate(double rate)
+{
+ Q_D(QTextToSpeechEngineWinRT);
+
+ d->rate = rate;
+ return true;
+}
+
+double QTextToSpeechEngineWinRT::pitch() const
+{
+ // Not supported for WinRT
+ Q_UNIMPLEMENTED();
+ return 1.;
+}
+
+bool QTextToSpeechEngineWinRT::setPitch(double pitch)
+{
+ // Not supported for WinRT
+ Q_UNUSED(pitch);
+ Q_UNIMPLEMENTED();
+ return false;
+}
+
+QLocale QTextToSpeechEngineWinRT::locale() const
+{
+ Q_D(const QTextToSpeechEngineWinRT);
+
+ HRESULT hr;
+ ComPtr<IVoiceInformation> info;
+ hr = d->synth->get_Voice(&info);
+
+ HString language;
+ hr = info->get_Language(language.GetAddressOf());
+
+ return QLocale(QString::fromWCharArray(language.GetRawBuffer(0)));
+}
+
+bool QTextToSpeechEngineWinRT::setLocale(const QLocale &locale)
+{
+ Q_D(QTextToSpeechEngineWinRT);
+
+ const int index = d->locales.indexOf(locale);
+ if (index == -1)
+ return false;
+
+ return setVoice(d->voices.at(index));
+}
+
+int QTextToSpeechEngineWinRT::volume() const
+{
+ Q_D(const QTextToSpeechEngineWinRT);
+
+ return d->volume;
+}
+
+bool QTextToSpeechEngineWinRT::setVolume(int volume)
+{
+ Q_D(QTextToSpeechEngineWinRT);
+
+ d->volume = volume;
+ return true;
+}
+
+QVoice QTextToSpeechEngineWinRT::voice() const
+{
+ Q_D(const QTextToSpeechEngineWinRT);
+
+ HRESULT hr;
+ ComPtr<IVoiceInformation> info;
+ hr = d->synth->get_Voice(&info);
+
+ return createVoiceForInformation(info);
+}
+
+bool QTextToSpeechEngineWinRT::setVoice(const QVoice &voice)
+{
+ Q_D(QTextToSpeechEngineWinRT);
+
+ const int index = d->voices.indexOf(voice);
+ if (index == -1)
+ return false;
+
+ HRESULT hr;
+ hr = d->synth->put_Voice(d->infos.at(index).Get());
+ return SUCCEEDED(hr);
+}
+
+QTextToSpeech::State QTextToSpeechEngineWinRT::state() const
+{
+ Q_D(const QTextToSpeechEngineWinRT);
+ return d->state;
+}
+
+void QTextToSpeechEngineWinRT::checkElementState()
+{
+ Q_D(QTextToSpeechEngineWinRT);
+
+ // MediaElement does not move into Stopped or Closed state when it finished
+ // playback of synthesised text. Instead it goes into Pause mode.
+ // Because of this MediaElement::add_MediaEnded() is not invoked and we
+ // cannot add an event listener to the Media Element to properly emit
+ // state changes.
+ // To still be able to capture when it is ready, use a periodic timer and
+ // check if the MediaElement went into Pause state.
+ bool finished = false;
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([d, &finished]() {
+ HRESULT hr;
+ ABI::Windows::UI::Xaml::Media::MediaElementState s;
+ hr = d->media.Get()->get_CurrentState(&s);
+ if (SUCCEEDED(hr) && s == MediaElementState_Paused)
+ finished = true;
+ return hr;
+ });
+
+ if (finished)
+ stop();
+}
+
+void QTextToSpeechEngineWinRT::init()
+{
+ Q_D(QTextToSpeechEngineWinRT);
+
+ d->state = QTextToSpeech::BackendError;
+
+ HRESULT hr;
+
+ hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
+ HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_Xaml_Markup_XamlReader).Get(),
+ IID_PPV_ARGS(&d->xamlReader));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ return hr;
+ });
+
+ ComPtr<IInstalledVoicesStatic> stat;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Media_SpeechSynthesis_SpeechSynthesizer).Get(),
+ IID_PPV_ARGS(&stat));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Media_SpeechSynthesis_SpeechSynthesizer).Get(),
+ &d->synth);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IVectorView<VoiceInformation*>> voices;
+ hr = stat->get_AllVoices(&voices);
+ RETURN_VOID_IF_FAILED("Could not get voice information.");
+
+ quint32 voiceSize;
+ hr = voices->get_Size(&voiceSize);
+ RETURN_VOID_IF_FAILED("Could not access size of voice information.");
+
+ for (quint32 i = 0; i < voiceSize; ++i) {
+ ComPtr<IVoiceInformation> info;
+ hr = voices->GetAt(i, &info);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ HString nativeLanguage;
+ hr = info->get_Language(nativeLanguage.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+
+ const QString languageString = QString::fromWCharArray(nativeLanguage.GetRawBuffer(0));
+ QLocale locale(languageString);
+ if (!d->locales.contains(locale))
+ d->locales.append(locale);
+
+ QVoice voice = createVoiceForInformation(info);
+ d->voices.append(voice);
+ d->infos.append(info);
+ }
+
+ d->state = QTextToSpeech::Ready;
+}
+
+QVoice QTextToSpeechEngineWinRT::createVoiceForInformation(ComPtr<IVoiceInformation> info) const
+{
+ HRESULT hr;
+ HString nativeName;
+ hr = info->get_DisplayName(nativeName.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+
+ const QString name = QString::fromWCharArray(nativeName.GetRawBuffer(0));
+
+ VoiceGender gender;
+ hr = info->get_Gender(&gender);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ return QTextToSpeechEngine::createVoice(name, gender == VoiceGender_Male ? QVoice::Male : QVoice::Female,
+ QVoice::Other, QVariant());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/tts/winrt/qtexttospeech_winrt.h b/src/plugins/tts/winrt/qtexttospeech_winrt.h
new file mode 100644
index 0000000..a39fc08
--- /dev/null
+++ b/src/plugins/tts/winrt/qtexttospeech_winrt.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Speech module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTTOSPEECHENGINE_WINRT_H
+#define QTEXTTOSPEECHENGINE_WINRT_H
+
+#include <QtTextToSpeech/qtexttospeechengine.h>
+#include <QtTextToSpeech/qvoice.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QVector>
+#include <QtCore/QString>
+#include <QtCore/QLocale>
+#include <QtCore/QScopedPointer>
+#include <QtCore/qt_windows.h>
+#include <wrl.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace Media {
+ namespace SpeechSynthesis {
+ struct IVoiceInformation;
+ }
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+class QTextToSpeechEngineWinRTPrivate;
+
+class QTextToSpeechEngineWinRT : public QTextToSpeechEngine
+{
+ Q_OBJECT
+
+public:
+ QTextToSpeechEngineWinRT(const QVariantMap &parameters, QObject *parent);
+ ~QTextToSpeechEngineWinRT();
+
+ QVector<QLocale> availableLocales() const Q_DECL_OVERRIDE;
+ QVector<QVoice> availableVoices() const Q_DECL_OVERRIDE;
+ void say(const QString &text) Q_DECL_OVERRIDE;
+ void stop() Q_DECL_OVERRIDE;
+ void pause() Q_DECL_OVERRIDE;
+ void resume() Q_DECL_OVERRIDE;
+ double rate() const Q_DECL_OVERRIDE;
+ bool setRate(double rate) Q_DECL_OVERRIDE;
+ double pitch() const Q_DECL_OVERRIDE;
+ bool setPitch(double pitch) Q_DECL_OVERRIDE;
+ QLocale locale() const Q_DECL_OVERRIDE;
+ bool setLocale(const QLocale &locale) Q_DECL_OVERRIDE;
+ int volume() const Q_DECL_OVERRIDE;
+ bool setVolume(int volume) Q_DECL_OVERRIDE;
+ QVoice voice() const Q_DECL_OVERRIDE;
+ bool setVoice(const QVoice &voice) Q_DECL_OVERRIDE;
+ QTextToSpeech::State state() const Q_DECL_OVERRIDE;
+
+public slots:
+ void checkElementState();
+private:
+ void init();
+ QVoice createVoiceForInformation(Microsoft::WRL::ComPtr<ABI::Windows::Media::SpeechSynthesis::IVoiceInformation> info) const;
+
+ QScopedPointer<QTextToSpeechEngineWinRTPrivate> d_ptr;
+ Q_DECLARE_PRIVATE(QTextToSpeechEngineWinRT)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/tts/winrt/qtexttospeech_winrt_plugin.cpp b/src/plugins/tts/winrt/qtexttospeech_winrt_plugin.cpp
new file mode 100644
index 0000000..16e8050
--- /dev/null
+++ b/src/plugins/tts/winrt/qtexttospeech_winrt_plugin.cpp
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Speech module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtexttospeech_winrt_plugin.h"
+#include "qtexttospeech_winrt.h"
+
+QTextToSpeechEngine *QTextToSpeechPluginWinRT::createTextToSpeechEngine(const QVariantMap &parameters, QObject *parent, QString *errorString) const
+{
+ Q_UNUSED(errorString)
+ return new QTextToSpeechEngineWinRT(parameters, parent);
+}
diff --git a/src/plugins/tts/winrt/qtexttospeech_winrt_plugin.h b/src/plugins/tts/winrt/qtexttospeech_winrt_plugin.h
new file mode 100644
index 0000000..4f92651
--- /dev/null
+++ b/src/plugins/tts/winrt/qtexttospeech_winrt_plugin.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the Qt Speech module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTTOSPEECHPLUGIN_WINRT_H
+#define QTEXTTOSPEECHPLUGIN_WINRT_H
+
+#include <QtCore/QObject>
+#include <QtCore/QLoggingCategory>
+#include <QtTextToSpeech/qtexttospeechplugin.h>
+#include <QtTextToSpeech/qtexttospeechengine.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTextToSpeechPluginWinRT : public QObject, public QTextToSpeechPlugin
+{
+ Q_OBJECT
+ Q_INTERFACES(QTextToSpeechPlugin)
+ Q_PLUGIN_METADATA(IID "org.qt-project.qt.speech.tts.plugin/5.0"
+ FILE "winrt_plugin.json")
+
+public:
+ QTextToSpeechEngine *createTextToSpeechEngine(
+ const QVariantMap &parameters,
+ QObject *parent,
+ QString *errorString) const;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/tts/winrt/winrt.pro b/src/plugins/tts/winrt/winrt.pro
new file mode 100644
index 0000000..6896620
--- /dev/null
+++ b/src/plugins/tts/winrt/winrt.pro
@@ -0,0 +1,18 @@
+TARGET = qtexttospeech_winrt
+PLUGIN_TYPE = texttospeech
+PLUGIN_CLASS_NAME = QTextToSpeechPluginWinRT
+
+load(qt_plugin)
+
+QT += core core-private texttospeech
+
+HEADERS += \
+ qtexttospeech_winrt.h \
+ qtexttospeech_winrt_plugin.h \
+
+SOURCES += \
+ qtexttospeech_winrt.cpp \
+ qtexttospeech_winrt_plugin.cpp \
+
+OTHER_FILES += \
+ winrt_plugin.json
diff --git a/src/plugins/tts/winrt/winrt_plugin.json b/src/plugins/tts/winrt/winrt_plugin.json
new file mode 100644
index 0000000..1f54076
--- /dev/null
+++ b/src/plugins/tts/winrt/winrt_plugin.json
@@ -0,0 +1,6 @@
+{
+ "Keys": ["winrt"],
+ "Provider": "winrt",
+ "Version": 100,
+ "Features": []
+}