├── .tag ├── qt_cmdline.cmake ├── examples ├── examples.pro ├── speech │ ├── quickspeech │ │ ├── qmldir │ │ ├── doc │ │ │ ├── images │ │ │ │ ├── buttons.png │ │ │ │ ├── status.gif │ │ │ │ └── quickspeech-example.png │ │ │ └── src │ │ │ │ └── quickspeech.qdoc │ │ ├── quickspeech.pro │ │ ├── main.cpp │ │ ├── CMakeLists.txt │ │ └── Main.qml │ ├── speech.pro │ ├── hello_speak │ │ ├── doc │ │ │ ├── images │ │ │ │ └── hellospeak-example.png │ │ │ └── src │ │ │ │ └── hellospeakex.qdoc │ │ ├── main.cpp │ │ ├── hello_speak.pro │ │ ├── mainwindow.h │ │ ├── CMakeLists.txt │ │ ├── mainwindow.cpp │ │ └── mainwindow.ui │ └── CMakeLists.txt └── CMakeLists.txt ├── src ├── CMakeLists.txt ├── tts │ ├── doc │ │ ├── QtTextToSpeechDoc │ │ ├── src │ │ │ ├── qttexttospeech-toc.qdoc │ │ │ ├── qttexttospeech-examples.qdoc │ │ │ ├── qttexttospeech.qdoc │ │ │ ├── qttexttospeech-index.qdoc │ │ │ ├── qt6-changes.qdoc │ │ │ └── qttexttospeech-engines.qdoc │ │ └── qttexttospeech.qdocconf │ ├── qt_cmdline.cmake │ ├── qml │ │ ├── CMakeLists.txt │ │ ├── qtexttospeech_qmltypes_p.h │ │ ├── qvoiceselector_p.h │ │ ├── qdeclarativetexttospeech_p.h │ │ ├── qvoiceselectorattached_p.h │ │ ├── qdeclarativetexttospeech.cpp │ │ └── qvoiceselectorattached.cpp │ ├── qtexttospeech_global.h │ ├── configure.cmake │ ├── qtexttospeechplugin.h │ ├── CMakeLists.txt │ ├── qtexttospeechplugin.cpp │ ├── qvoice_p.h │ ├── qtexttospeech_p.h │ ├── configure.json │ ├── qtexttospeechengine.h │ ├── qvoice.h │ ├── qtexttospeechengine.cpp │ └── qvoice.cpp └── plugins │ ├── tts │ ├── android │ │ ├── CMakeLists.txt │ │ ├── src │ │ │ ├── android_plugin.json │ │ │ ├── CMakeLists.txt │ │ │ ├── qtexttospeech_android_plugin.cpp │ │ │ ├── qtexttospeech_android_plugin.h │ │ │ └── qtexttospeech_android.h │ │ └── jar │ │ │ ├── AndroidManifest.xml │ │ │ └── CMakeLists.txt │ ├── speechdispatcher │ │ ├── speechd_plugin.json │ │ ├── qtexttospeech_speechd_plugin.cpp │ │ ├── CMakeLists.txt │ │ ├── qtexttospeech_speechd_plugin.h │ │ └── qtexttospeech_speechd.h │ ├── mock │ │ ├── mock_plugin.json │ │ ├── CMakeLists.txt │ │ ├── qtexttospeech_mock_plugin.cpp │ │ ├── qtexttospeech_mock_plugin.h │ │ └── qtexttospeech_mock.h │ ├── sapi │ │ ├── sapi_plugin.json │ │ ├── qtexttospeech_sapi_plugin.cpp │ │ ├── CMakeLists.txt │ │ ├── qtexttospeech_sapi_plugin.h │ │ └── qtexttospeech_sapi.h │ ├── flite │ │ ├── flite_plugin.json │ │ ├── qtexttospeech_flite_plugin.cpp │ │ ├── CMakeLists.txt │ │ ├── qtexttospeech_flite_plugin.h │ │ ├── qtexttospeech_flite.h │ │ ├── qtexttospeech_flite_processor.h │ │ └── qtexttospeech_flite.cpp │ ├── winrt │ │ ├── winrt_plugin.json │ │ ├── qtexttospeech_winrt_plugin.cpp │ │ ├── CMakeLists.txt │ │ ├── qtexttospeech_winrt_plugin.h │ │ ├── qtexttospeech_winrt.h │ │ └── qtexttospeech_winrt_audiosource.h │ ├── darwin │ │ ├── darwin_plugin.json │ │ ├── qtexttospeech_darwin_plugin.cpp │ │ ├── CMakeLists.txt │ │ ├── qtexttospeech_darwin_plugin.h │ │ └── qtexttospeech_darwin.h │ └── CMakeLists.txt │ └── CMakeLists.txt ├── configure.json ├── .gitreview ├── config_help.txt ├── tests ├── auto │ ├── CMakeLists.txt │ ├── qtexttospeech │ │ ├── BLACKLIST │ │ └── CMakeLists.txt │ ├── qvoice │ │ ├── CMakeLists.txt │ │ └── tst_qvoice.cpp │ └── qtexttospeech_qml │ │ ├── main.cpp │ │ ├── CMakeLists.txt │ │ ├── tst_voice.qml │ │ └── tst_texttospeech.qml └── CMakeLists.txt ├── .cmake.conf ├── dist ├── REUSE.toml ├── changes-5.12.0 ├── changes-5.13.0 ├── changes-5.14.0 ├── changes-5.15.0 ├── changes-5.12.1 ├── changes-5.13.1 ├── changes-5.14.1 ├── changes-5.15.1 ├── changes-5.11.3 ├── changes-5.12.2 ├── changes-5.12.3 ├── changes-5.12.4 ├── changes-5.12.5 ├── changes-5.13.2 ├── changes-5.14.2 ├── changes-5.11.2 └── changes-5.11.1 ├── dependencies.yaml ├── LICENSES ├── LicenseRef-Qt-Commercial.txt ├── BSD-3-Clause.txt └── LGPL-3.0-only.txt ├── coin ├── module_config.yaml └── axivion │ └── ci_config_linux.json ├── configure.cmake ├── cmake ├── FindSpeechDispatcher.cmake └── FindFlite.cmake ├── CMakeLists.txt ├── REUSE.toml └── licenseRule.json /.tag: -------------------------------------------------------------------------------- 1 | e2631758f85ecdadb32bb7bd6579d201941933bb 2 | -------------------------------------------------------------------------------- /qt_cmdline.cmake: -------------------------------------------------------------------------------- 1 | qt_commandline_subconfig(src/tts) 2 | -------------------------------------------------------------------------------- /examples/examples.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | SUBDIRS = speech 3 | -------------------------------------------------------------------------------- /examples/speech/quickspeech/qmldir: -------------------------------------------------------------------------------- 1 | module main 2 | Main 1.0 Main.qml 3 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(tts) 2 | add_subdirectory(plugins) 3 | -------------------------------------------------------------------------------- /src/tts/doc/QtTextToSpeechDoc: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /configure.json: -------------------------------------------------------------------------------- 1 | { 2 | "subconfigs": [ 3 | "src/tts" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /src/plugins/tts/android/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(jar) 2 | add_subdirectory(src) 3 | -------------------------------------------------------------------------------- /.gitreview: -------------------------------------------------------------------------------- 1 | [gerrit] 2 | host=codereview.qt-project.org 3 | project=qt/qtspeech 4 | defaultbranch=dev 5 | -------------------------------------------------------------------------------- /examples/speech/quickspeech/doc/images/buttons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qt/qtspeech/dev/examples/speech/quickspeech/doc/images/buttons.png -------------------------------------------------------------------------------- /examples/speech/quickspeech/doc/images/status.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qt/qtspeech/dev/examples/speech/quickspeech/doc/images/status.gif -------------------------------------------------------------------------------- /examples/speech/speech.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | qtHaveModule(widgets): SUBDIRS += hello_speak 3 | qtHaveModule(quick): SUBDIRS += quickspeech 4 | -------------------------------------------------------------------------------- /examples/speech/hello_speak/doc/images/hellospeak-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qt/qtspeech/dev/examples/speech/hello_speak/doc/images/hellospeak-example.png -------------------------------------------------------------------------------- /examples/speech/quickspeech/doc/images/quickspeech-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qt/qtspeech/dev/examples/speech/quickspeech/doc/images/quickspeech-example.png -------------------------------------------------------------------------------- /config_help.txt: -------------------------------------------------------------------------------- 1 | TextToSpeech options: 2 | 3 | -flite ............... Enable Flite support [auto] (Unix only) 4 | -speechd ............. Enable speech dispatcher support [auto] (Unix only) 5 | -------------------------------------------------------------------------------- /tests/auto/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(qtexttospeech) 2 | if(TARGET Qt::Qml AND TARGET Qt::QuickTest) 3 | add_subdirectory(qtexttospeech_qml) 4 | endif() 5 | add_subdirectory(qvoice) 6 | -------------------------------------------------------------------------------- /src/tts/qt_cmdline.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | qt_commandline_option(flite TYPE boolean) 5 | qt_commandline_option(speechd TYPE boolean) 6 | -------------------------------------------------------------------------------- /tests/auto/qtexttospeech/BLACKLIST: -------------------------------------------------------------------------------- 1 | [pauseResume:darwin] 2 | macos-13 ci # QTBUG-108205 3 | macos-15 arm ci # QTBUG-108205 4 | macos-26 arm ci # QTBUG-108205 5 | [sayingWordWithPause:darwin] 6 | macos-13 ci # QTBUG-108205 7 | -------------------------------------------------------------------------------- /.cmake.conf: -------------------------------------------------------------------------------- 1 | set(QT_REPO_MODULE_VERSION "6.12.0") 2 | set(QT_EXTRA_INTERNAL_TARGET_DEFINES 3 | "QT_NO_AS_CONST=1" 4 | "QT_NO_CONTEXTLESS_CONNECT=1" 5 | "QT_NO_FOREACH=1" 6 | "QT_NO_URL_CAST_FROM_STRING=1" 7 | ) 8 | -------------------------------------------------------------------------------- /src/plugins/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # Generated from plugins.pro. 5 | 6 | if(TARGET Qt::TextToSpeech) 7 | add_subdirectory(tts) 8 | endif() 9 | -------------------------------------------------------------------------------- /src/plugins/tts/speechdispatcher/speechd_plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "Keys": ["speechd"], 3 | "Provider": "speechd", 4 | "Version": 100, 5 | "Priority": 80, 6 | "Capabilities": [ 7 | "Speak", 8 | "PauseResume" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /tests/auto/qvoice/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | qt_internal_add_test(tst_qvoice 5 | SOURCES 6 | tst_qvoice.cpp 7 | LIBRARIES 8 | Qt::TextToSpeechPrivate 9 | ) 10 | -------------------------------------------------------------------------------- /tests/auto/qtexttospeech_qml/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2016 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only 3 | 4 | #include 5 | #include 6 | 7 | QUICK_TEST_MAIN(tst_qtexttospeech_qml) 8 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause 3 | 4 | # Generated from examples.pro. 5 | 6 | qt_examples_build_begin() 7 | 8 | add_subdirectory(speech) 9 | 10 | qt_examples_build_end() 11 | -------------------------------------------------------------------------------- /dist/REUSE.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[annotations]] 4 | path = ["*"] 5 | precedence = "override" 6 | comment = "Licensed as documentation." 7 | SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." 8 | SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only" 9 | -------------------------------------------------------------------------------- /src/plugins/tts/android/src/android_plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "Keys": ["android"], 3 | "Provider": "android", 4 | "Version": 100, 5 | "Priority": 100, 6 | "Capabilities": [ 7 | "Speak", 8 | "WordByWordProgress", 9 | "Synthesize" 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /src/plugins/tts/mock/mock_plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "Keys": ["mock"], 3 | "Provider": "mock", 4 | "Version": 100, 5 | "Priority": -1, 6 | "Capabilities": [ 7 | "Speak", 8 | "PauseResume", 9 | "Synthesize", 10 | "WordByWordProgress" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/plugins/tts/sapi/sapi_plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "Keys": ["sapi"], 3 | "Provider": "sapi", 4 | "Version": 100, 5 | "Priority": 50, 6 | "Capabilities": [ 7 | "Speak", 8 | "PauseResume", 9 | "WordByWordProgress", 10 | "Synthesize" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/plugins/tts/flite/flite_plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "Keys": ["flite"], 3 | "Provider": "flite", 4 | "Version": 100, 5 | "Priority": 50, 6 | "Capabilities": [ 7 | "Speak", 8 | "PauseResume", 9 | "WordByWordProgress", 10 | "Synthesize" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/plugins/tts/winrt/winrt_plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "Keys": ["winrt"], 3 | "Provider": "winrt", 4 | "Version": 100, 5 | "Priority": 80, 6 | "Capabilities": [ 7 | "Speak", 8 | "PauseResume", 9 | "WordByWordProgress", 10 | "Synthesize" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | if(QT_BUILD_STANDALONE_TESTS) 5 | # Add qt_find_package calls for extra dependencies that need to be found when building 6 | # the standalone tests here. 7 | endif() 8 | qt_build_tests() 9 | -------------------------------------------------------------------------------- /src/plugins/tts/darwin/darwin_plugin.json: -------------------------------------------------------------------------------- 1 | { 2 | "Keys": ["darwin"], 3 | "Provider": "darwin", 4 | "Version": 100, 5 | "Priority": 100, 6 | "Capabilities": [ 7 | "Speak", 8 | "PauseResume", 9 | "WordByWordProgress", 10 | "Synthesize" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /dependencies.yaml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | ../qtbase: 3 | ref: df1292e2b96aab02ad6df778d8336e7958ad5d1c 4 | required: true 5 | ../qtdeclarative: 6 | ref: 7ef1d06ce70fa360613dca0b5ff03365ebbc9883 7 | required: false 8 | ../qtmultimedia: 9 | ref: a2ff9baab792bf5d0bf2d7d626f7959329ef35d7 10 | required: true 11 | -------------------------------------------------------------------------------- /examples/speech/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause 3 | 4 | # Generated from speech.pro. 5 | 6 | if(TARGET Qt::Widgets) 7 | qt_internal_add_example(hello_speak) 8 | endif() 9 | if(TARGET Qt::Quick) 10 | qt_internal_add_example(quickspeech) 11 | endif() 12 | -------------------------------------------------------------------------------- /examples/speech/hello_speak/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause 3 | 4 | #include "mainwindow.h" 5 | 6 | #include 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | QApplication app(argc, argv); 11 | MainWindow win; 12 | win.show(); 13 | return app.exec(); 14 | } 15 | -------------------------------------------------------------------------------- /tests/auto/qtexttospeech_qml/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB_RECURSE test_data_glob 2 | RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} 3 | *.qml) 4 | list(APPEND test_data ${test_data_glob}) 5 | 6 | qt_internal_add_test(tst_qtexttospeech_qml 7 | QMLTEST 8 | SOURCES 9 | main.cpp 10 | LIBRARIES 11 | Qt::TextToSpeech 12 | Qt::Qml 13 | TESTDATA ${test_data} 14 | ) 15 | -------------------------------------------------------------------------------- /examples/speech/hello_speak/hello_speak.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | QT += widgets texttospeech 4 | requires(qtHaveModule(gui)) 5 | qtHaveModule(gui): requires(qtConfig(combobox)) 6 | 7 | SOURCES = main.cpp \ 8 | mainwindow.cpp 9 | HEADERS = mainwindow.h 10 | 11 | FORMS = mainwindow.ui 12 | 13 | # install 14 | target.path = $$[QT_INSTALL_EXAMPLES]/speech/hello_speak 15 | INSTALLS += target 16 | -------------------------------------------------------------------------------- /src/plugins/tts/android/jar/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/speech/quickspeech/quickspeech.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | TARGET = quickspeech 3 | 4 | QT += quick texttospeech 5 | 6 | SOURCES += main.cpp 7 | 8 | qml_resources.files = \ 9 | qmldir \ 10 | Main.qml 11 | 12 | qml_resources.prefix = /qt/qml/main 13 | 14 | RESOURCES += qml_resources 15 | 16 | target.path = $$[QT_INSTALL_EXAMPLES]/speech/quickspeech 17 | INSTALLS += target 18 | 19 | DISTFILES += \ 20 | qmldir 21 | -------------------------------------------------------------------------------- /src/plugins/tts/mock/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | qt_internal_add_plugin(QTextToSpeechMockPlugin 5 | OUTPUT_NAME qtexttospeech_mock 6 | PLUGIN_TYPE texttospeech 7 | SOURCES 8 | qtexttospeech_mock.cpp qtexttospeech_mock.h 9 | qtexttospeech_mock_plugin.cpp qtexttospeech_mock_plugin.h 10 | LIBRARIES 11 | Qt::Core 12 | Qt::TextToSpeech 13 | ) 14 | -------------------------------------------------------------------------------- /LICENSES/LicenseRef-Qt-Commercial.txt: -------------------------------------------------------------------------------- 1 | Licensees holding valid commercial Qt licenses may use this software in 2 | accordance with the the terms contained in a written agreement between 3 | you and The Qt Company. Alternatively, the terms and conditions that were 4 | accepted by the licensee when buying and/or downloading the 5 | software do apply. 6 | 7 | For the latest licensing terms and conditions, see https://www.qt.io/terms-conditions. 8 | For further information use the contact form at https://www.qt.io/contact-us. 9 | -------------------------------------------------------------------------------- /coin/module_config.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | accept_configuration: 3 | condition: property 4 | property: features 5 | not_contains_value: Disable 6 | 7 | instructions: 8 | Build: 9 | - type: EnvironmentVariable 10 | variableName: VERIFY_SOURCE_SBOM 11 | variableValue: "ON" 12 | - !include "{{qt/qtbase}}/coin_module_build_template_v2.yaml" 13 | 14 | Test: 15 | - !include "{{qt/qtbase}}/coin_module_test_template_v3.yaml" 16 | - !include "{{qt/qtbase}}/coin_module_test_docs.yaml" 17 | -------------------------------------------------------------------------------- /src/tts/doc/src/qttexttospeech-toc.qdoc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only 3 | 4 | /*! 5 | \page qttexttospeech-toc.html 6 | \title Qt TextToSpeech module topics 7 | 8 | The following list has links to all the individual topics (HTML files) 9 | in the Qt TextToSpeech module. 10 | 11 | \list 12 | \li \l {Qt TextToSpeech Engines} 13 | \li \l {Changes to Qt TextToSpeech}{Upgrading from Qt 5} 14 | \endlist 15 | 16 | */ 17 | -------------------------------------------------------------------------------- /src/tts/qml/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2023 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | qt_internal_add_qml_module(TextToSpeechQml 5 | URI "QtTextToSpeech" 6 | VERSION "${PROJECT_VERSION}" 7 | PLUGIN_TARGET TextToSpeechQml 8 | SOURCES 9 | qtexttospeech_qmltypes_p.h 10 | qdeclarativetexttospeech.cpp qdeclarativetexttospeech_p.h 11 | qvoiceselectorattached.cpp qvoiceselectorattached_p.h 12 | LIBRARIES 13 | Qt::TextToSpeech 14 | NO_GENERATE_CPP_EXPORTS 15 | ) 16 | -------------------------------------------------------------------------------- /configure.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | 5 | 6 | #### Inputs 7 | 8 | 9 | 10 | #### Libraries 11 | 12 | 13 | 14 | #### Tests 15 | 16 | 17 | 18 | #### Features 19 | 20 | 21 | qt_extra_definition("QT_VERSION_STR" "\"${PROJECT_VERSION}\"" PUBLIC) 22 | qt_extra_definition("QT_VERSION_MAJOR" ${PROJECT_VERSION_MAJOR} PUBLIC) 23 | qt_extra_definition("QT_VERSION_MINOR" ${PROJECT_VERSION_MINOR} PUBLIC) 24 | qt_extra_definition("QT_VERSION_PATCH" ${PROJECT_VERSION_PATCH} PUBLIC) 25 | -------------------------------------------------------------------------------- /src/plugins/tts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | add_subdirectory(mock) 5 | if(QT_FEATURE_speechd AND UNIX) 6 | add_subdirectory(speechdispatcher) 7 | endif() 8 | if(WIN32) 9 | add_subdirectory(sapi) 10 | if(NOT MINGW) 11 | add_subdirectory(winrt) 12 | endif() 13 | endif() 14 | if(APPLE) 15 | add_subdirectory(darwin) 16 | endif() 17 | if(ANDROID) 18 | add_subdirectory(android) 19 | endif() 20 | if(QT_FEATURE_flite) 21 | add_subdirectory(flite) 22 | endif() 23 | -------------------------------------------------------------------------------- /src/plugins/tts/android/jar/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2024 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | set(java_sources 5 | src/org/qtproject/qt/android/speech/QtTextToSpeech.java 6 | ) 7 | 8 | qt_internal_add_jar(QtAndroidTextToSpeech 9 | INCLUDE_JARS ${QT_ANDROID_JAR} 10 | SOURCES ${java_sources} 11 | OUTPUT_DIR "${QT_BUILD_DIR}/jar" 12 | ) 13 | 14 | qt_path_join(destination ${INSTALL_DATADIR} "jar") 15 | 16 | install_jar(QtAndroidTextToSpeech 17 | DESTINATION ${destination} 18 | COMPONENT Devel 19 | ) 20 | -------------------------------------------------------------------------------- /src/tts/doc/src/qttexttospeech-examples.qdoc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only 3 | 4 | /*! 5 | \group qttexttospeech_examples 6 | \title Qt TextToSpeech Examples 7 | \brief Demonstrates the text-to-speech functionality provided by Qt. 8 | 9 | The \l{Qt TextToSpeech} module provides cross-platform text-to-speech capabilities 10 | for Qt based applications. 11 | 12 | The examples listed below show some typical use cases in both C++ and QML. 13 | */ 14 | -------------------------------------------------------------------------------- /src/plugins/tts/mock/qtexttospeech_mock_plugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qtexttospeech_mock_plugin.h" 6 | #include "qtexttospeech_mock.h" 7 | 8 | QTextToSpeechEngine *QTextToSpeechMockPlugin::createTextToSpeechEngine(const QVariantMap ¶meters, QObject *parent, QString *errorString) const 9 | { 10 | Q_UNUSED(errorString); 11 | return new QTextToSpeechEngineMock(parameters, parent); 12 | } 13 | -------------------------------------------------------------------------------- /src/plugins/tts/sapi/qtexttospeech_sapi_plugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qtexttospeech_sapi_plugin.h" 6 | #include "qtexttospeech_sapi.h" 7 | 8 | QTextToSpeechEngine *QTextToSpeechSapiPlugin::createTextToSpeechEngine(const QVariantMap ¶meters, QObject *parent, QString *errorString) const 9 | { 10 | Q_UNUSED(errorString); 11 | return new QTextToSpeechEngineSapi(parameters, parent); 12 | } 13 | -------------------------------------------------------------------------------- /src/plugins/tts/winrt/qtexttospeech_winrt_plugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qtexttospeech_winrt_plugin.h" 6 | #include "qtexttospeech_winrt.h" 7 | 8 | QTextToSpeechEngine *QTextToSpeechWinRTPlugin::createTextToSpeechEngine(const QVariantMap ¶meters, QObject *parent, QString *errorString) const 9 | { 10 | Q_UNUSED(errorString); 11 | return new QTextToSpeechEngineWinRT(parameters, parent); 12 | } 13 | -------------------------------------------------------------------------------- /src/plugins/tts/darwin/qtexttospeech_darwin_plugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qtexttospeech_darwin_plugin.h" 6 | #include "qtexttospeech_darwin.h" 7 | 8 | QTextToSpeechEngine *QTextToSpeechDarwinPlugin::createTextToSpeechEngine(const QVariantMap ¶meters, QObject *parent, QString *errorString) const 9 | { 10 | Q_UNUSED(errorString); 11 | return new QTextToSpeechEngineDarwin(parameters, parent); 12 | } 13 | -------------------------------------------------------------------------------- /examples/speech/quickspeech/main.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause 3 | 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | QGuiApplication app(argc, argv); 10 | 11 | QQmlApplicationEngine engine; 12 | QObject::connect(&engine, &QQmlApplicationEngine::objectCreationFailed, 13 | &app, []() { QCoreApplication::exit(-1); }, 14 | Qt::QueuedConnection); 15 | engine.loadFromModule("main", "Main"); 16 | 17 | return app.exec(); 18 | } 19 | -------------------------------------------------------------------------------- /src/plugins/tts/speechdispatcher/qtexttospeech_speechd_plugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qtexttospeech_speechd_plugin.h" 6 | #include "qtexttospeech_speechd.h" 7 | 8 | QTextToSpeechEngine *QTextToSpeechSpeechdPlugin::createTextToSpeechEngine(const QVariantMap ¶meters, QObject *parent, QString *errorString) const 9 | { 10 | Q_UNUSED(errorString); 11 | return new QTextToSpeechEngineSpeechd(parameters, parent); 12 | } 13 | -------------------------------------------------------------------------------- /src/tts/doc/src/qttexttospeech.qdoc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only 3 | 4 | /*! 5 | \module QtTextToSpeech 6 | \title Qt TextToSpeech C++ Classes 7 | \ingroup modules 8 | \qtcmakepackage TextToSpeech 9 | \qtvariable texttospeech 10 | 11 | \brief provides C++ API to access text-to-speech engines. 12 | */ 13 | 14 | /*! 15 | \qmlmodule QtTextToSpeech 16 | \title Qt TextToSpeech QML Types 17 | \ingroup qmlmodules 18 | 19 | \brief provides QML types to access text-to-speech functionality. 20 | */ 21 | -------------------------------------------------------------------------------- /src/plugins/tts/darwin/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | qt_internal_find_apple_system_framework(FWAVFoundation AVFoundation) 5 | 6 | qt_internal_add_plugin(QTextToSpeechDarwinPlugin 7 | OUTPUT_NAME qtexttospeech_speechdarwin 8 | PLUGIN_TYPE texttospeech 9 | SOURCES 10 | qtexttospeech_darwin.h qtexttospeech_darwin.mm 11 | qtexttospeech_darwin_plugin.cpp qtexttospeech_darwin_plugin.h 12 | LIBRARIES 13 | Qt::Core 14 | Qt::Gui 15 | Qt::TextToSpeech 16 | Qt::Multimedia 17 | ${FWAVFoundation} 18 | ) 19 | -------------------------------------------------------------------------------- /src/plugins/tts/speechdispatcher/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | qt_internal_add_plugin(QTextToSpeechSpeechdPlugin 5 | OUTPUT_NAME qtexttospeech_speechd 6 | PLUGIN_TYPE texttospeech 7 | SOURCES 8 | qtexttospeech_speechd.cpp qtexttospeech_speechd.h 9 | qtexttospeech_speechd_plugin.cpp qtexttospeech_speechd_plugin.h 10 | LIBRARIES 11 | Qt::Core 12 | Qt::TextToSpeech 13 | ) 14 | 15 | qt_internal_extend_target(QTextToSpeechSpeechdPlugin CONDITION QT_FEATURE_speechd 16 | LIBRARIES 17 | SpeechDispatcher::SpeechDispatcher 18 | ) 19 | -------------------------------------------------------------------------------- /src/tts/qtexttospeech_global.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECH_GLOBAL_H 6 | #define QTEXTTOSPEECH_GLOBAL_H 7 | 8 | #include 9 | 10 | QT_BEGIN_NAMESPACE 11 | 12 | #ifndef QT_STATIC 13 | # if defined(QTEXTTOSPEECH_LIBRARY) 14 | # define Q_TEXTTOSPEECH_EXPORT Q_DECL_EXPORT 15 | # else 16 | # define Q_TEXTTOSPEECH_EXPORT Q_DECL_IMPORT 17 | # endif 18 | #else 19 | # define Q_TEXTTOSPEECH_EXPORT 20 | #endif 21 | 22 | QT_END_NAMESPACE 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/plugins/tts/android/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | qt_internal_add_plugin(QTextToSpeechEngineAndroidPlugin 5 | OUTPUT_NAME qttexttospeech_android 6 | PLUGIN_TYPE texttospeech 7 | CLASS_NAME QTextToSpeechEngineAndroid 8 | SOURCES 9 | qtexttospeech_android.cpp qtexttospeech_android.h 10 | qtexttospeech_android_plugin.cpp qtexttospeech_android_plugin.h 11 | LIBRARIES 12 | Qt::Core 13 | Qt::CorePrivate 14 | Qt::TextToSpeech 15 | Qt::Multimedia 16 | ) 17 | 18 | add_dependencies(QTextToSpeechEngineAndroidPlugin QtAndroidTextToSpeech) 19 | -------------------------------------------------------------------------------- /cmake/FindSpeechDispatcher.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # We can't create the same interface imported target multiple times, CMake will complain if we do 5 | # that. This can happen if the find_package call is done in multiple different subdirectories. 6 | if(TARGET SpeechDispatcher::SpeechDispatcher) 7 | set(SpeechDispatcher_FOUND 1) 8 | return() 9 | endif() 10 | 11 | find_package(PkgConfig QUIET) 12 | 13 | pkg_check_modules(SpeechDispatcher "speech-dispatcher" IMPORTED_TARGET GLOBAL) 14 | 15 | if (TARGET PkgConfig::SpeechDispatcher) 16 | add_library(SpeechDispatcher::SpeechDispatcher ALIAS PkgConfig::SpeechDispatcher) 17 | endif() 18 | -------------------------------------------------------------------------------- /src/plugins/tts/flite/qtexttospeech_flite_plugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qtexttospeech_flite_plugin.h" 6 | #include "qtexttospeech_flite.h" 7 | 8 | QT_BEGIN_NAMESPACE 9 | 10 | Q_LOGGING_CATEGORY(lcSpeechTtsFlite, "qt.speech.tts.flite") 11 | 12 | QTextToSpeechEngine *QTextToSpeechFlitePlugin::createTextToSpeechEngine( 13 | const QVariantMap ¶meters, QObject *parent, QString *errorString) const 14 | { 15 | Q_UNUSED(errorString); 16 | return new QTextToSpeechEngineFlite(parameters, parent); 17 | } 18 | 19 | QT_END_NAMESPACE 20 | -------------------------------------------------------------------------------- /tests/auto/qtexttospeech/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | qt_internal_add_test(tst_qtexttospeech 5 | SOURCES 6 | tst_qtexttospeech.cpp 7 | LIBRARIES 8 | Qt::TextToSpeechPrivate 9 | Qt::Multimedia 10 | ) 11 | 12 | # on macOS we need to run a Cocoa event dispatcher 13 | qt_internal_extend_target(tst_qtexttospeech CONDITION MACOS 14 | LIBRARIES 15 | Qt::Gui 16 | ) 17 | 18 | # for a standalone test build we have to find_package SpeechDispatcher again 19 | find_package(SpeechDispatcher) 20 | qt_internal_extend_target(tst_qtexttospeech CONDITION QT_FEATURE_speechd 21 | LIBRARIES 22 | SpeechDispatcher::SpeechDispatcher 23 | ) 24 | -------------------------------------------------------------------------------- /src/plugins/tts/sapi/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | qt_internal_add_plugin(QTextToSpeechSapiPlugin 5 | OUTPUT_NAME qtexttospeech_sapi 6 | PLUGIN_TYPE texttospeech 7 | SOURCES 8 | qtexttospeech_sapi.cpp qtexttospeech_sapi.h 9 | qtexttospeech_sapi_plugin.cpp qtexttospeech_sapi_plugin.h 10 | LIBRARIES 11 | Qt::Core 12 | Qt::TextToSpeech 13 | ) 14 | 15 | qt_internal_extend_target(QTextToSpeechSapiPlugin CONDITION MSVC 16 | COMPILE_OPTIONS 17 | /Zc:strictStrings 18 | ) 19 | 20 | qt_internal_extend_target(QTextToSpeechSapiPlugin CONDITION MINGW 21 | LIBRARIES 22 | ole32 23 | sapi 24 | uuid 25 | ) 26 | -------------------------------------------------------------------------------- /src/plugins/tts/flite/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS Concurrent MultimediaPrivate) 5 | 6 | qt_internal_add_plugin(QTextToSpeechFlitePlugin 7 | OUTPUT_NAME qtexttospeech_flite 8 | PLUGIN_TYPE texttospeech 9 | SOURCES 10 | qtexttospeech_flite.cpp qtexttospeech_flite.h 11 | qtexttospeech_flite_plugin.cpp qtexttospeech_flite_plugin.h 12 | qtexttospeech_flite_processor.cpp qtexttospeech_flite_processor.h 13 | LIBRARIES 14 | Flite::Flite 15 | Qt::Concurrent 16 | Qt::Core 17 | Qt::Multimedia 18 | Qt::MultimediaPrivate 19 | Qt::TextToSpeech 20 | ) 21 | -------------------------------------------------------------------------------- /dist/changes-5.12.0: -------------------------------------------------------------------------------- 1 | Qt 5.12 introduces many new features and improvements as well as bugfixes 2 | over the 5.11.x series. For more details, refer to the online documentation 3 | included in this distribution. The documentation is also available online: 4 | 5 | https://doc.qt.io/qt-5/index.html 6 | 7 | The Qt version 5.12 series is binary compatible with the 5.11.x series. 8 | Applications compiled for 5.11 will continue to run with 5.12. 9 | 10 | Some of the changes listed in this file include issue tracking numbers 11 | corresponding to tasks in the Qt Bug Tracker: 12 | 13 | https://bugreports.qt.io/ 14 | 15 | Each of these identifiers can be entered in the bug tracker to obtain more 16 | information about a particular change. 17 | 18 | - This release contains only minor code improvements. 19 | -------------------------------------------------------------------------------- /dist/changes-5.13.0: -------------------------------------------------------------------------------- 1 | Qt 5.13 introduces many new features and improvements as well as bugfixes 2 | over the 5.12.x series. For more details, refer to the online documentation 3 | included in this distribution. The documentation is also available online: 4 | 5 | https://doc.qt.io/qt-5/index.html 6 | 7 | The Qt version 5.13 series is binary compatible with the 5.12.x series. 8 | Applications compiled for 5.12 will continue to run with 5.13. 9 | 10 | Some of the changes listed in this file include issue tracking numbers 11 | corresponding to tasks in the Qt Bug Tracker: 12 | 13 | https://bugreports.qt.io/ 14 | 15 | Each of these identifiers can be entered in the bug tracker to obtain more 16 | information about a particular change. 17 | 18 | - This release contains only minor code improvements. 19 | -------------------------------------------------------------------------------- /dist/changes-5.14.0: -------------------------------------------------------------------------------- 1 | Qt 5.14 introduces many new features and improvements as well as bugfixes 2 | over the 5.13.x series. For more details, refer to the online documentation 3 | included in this distribution. The documentation is also available online: 4 | 5 | https://doc.qt.io/qt-5/index.html 6 | 7 | The Qt version 5.14 series is binary compatible with the 5.13.x series. 8 | Applications compiled for 5.13 will continue to run with 5.14. 9 | 10 | Some of the changes listed in this file include issue tracking numbers 11 | corresponding to tasks in the Qt Bug Tracker: 12 | 13 | https://bugreports.qt.io/ 14 | 15 | Each of these identifiers can be entered in the bug tracker to obtain more 16 | information about a particular change. 17 | 18 | - This release contains only minor code improvements. 19 | -------------------------------------------------------------------------------- /dist/changes-5.15.0: -------------------------------------------------------------------------------- 1 | Qt 5.15 introduces many new features and improvements as well as bugfixes 2 | over the 5.14.x series. For more details, refer to the online documentation 3 | included in this distribution. The documentation is also available online: 4 | 5 | https://doc.qt.io/qt-5/index.html 6 | 7 | The Qt version 5.15 series is binary compatible with the 5.14.x series. 8 | Applications compiled for 5.14 will continue to run with 5.15. 9 | 10 | Some of the changes listed in this file include issue tracking numbers 11 | corresponding to tasks in the Qt Bug Tracker: 12 | 13 | https://bugreports.qt.io/ 14 | 15 | Each of these identifiers can be entered in the bug tracker to obtain more 16 | information about a particular change. 17 | 18 | - This release contains only minor code improvements. 19 | -------------------------------------------------------------------------------- /src/plugins/tts/winrt/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | qt_internal_add_plugin(QTextToSpeechWinRTPlugin 5 | OUTPUT_NAME qtexttospeech_winrt 6 | PLUGIN_TYPE texttospeech 7 | SOURCES 8 | qtexttospeech_winrt.cpp qtexttospeech_winrt.h 9 | qtexttospeech_winrt_audiosource.cpp qtexttospeech_winrt_audiosource.h 10 | qtexttospeech_winrt_plugin.cpp qtexttospeech_winrt_plugin.h 11 | LIBRARIES 12 | Qt::Core 13 | Qt::CorePrivate 14 | Qt::TextToSpeech 15 | Qt::Multimedia 16 | Qt::MultimediaPrivate 17 | shlwapi 18 | runtimeobject 19 | ) 20 | 21 | qt_internal_extend_target(QTextToSpeechWinRTPlugin CONDITION MSVC 22 | COMPILE_OPTIONS 23 | /Zc:twoPhase- 24 | ) 25 | -------------------------------------------------------------------------------- /dist/changes-5.12.1: -------------------------------------------------------------------------------- 1 | Qt 5.12.1 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.12.0. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | http://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.12 series is binary compatible with the 5.11.x series. 10 | Applications compiled for 5.11 will continue to run with 5.12. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | - This release contains only minor code improvements. 21 | -------------------------------------------------------------------------------- /dist/changes-5.13.1: -------------------------------------------------------------------------------- 1 | Qt 5.13.1 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.13.0. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | https://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.13 series is binary compatible with the 5.12.x series. 10 | Applications compiled for 5.12 will continue to run with 5.13. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | - This release contains only minor code improvements. 21 | -------------------------------------------------------------------------------- /dist/changes-5.14.1: -------------------------------------------------------------------------------- 1 | Qt 5.14.1 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.14.0. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | https://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.14 series is binary compatible with the 5.13.x series. 10 | Applications compiled for 5.13 will continue to run with 5.14. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | - This release contains only minor code improvements. 21 | -------------------------------------------------------------------------------- /dist/changes-5.15.1: -------------------------------------------------------------------------------- 1 | Qt 5.15.1 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.15.0. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | https://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.15 series is binary compatible with the 5.14.x series. 10 | Applications compiled for 5.14 will continue to run with 5.15. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | - This release contains only minor code improvements. 21 | -------------------------------------------------------------------------------- /tests/auto/qtexttospeech_qml/tst_voice.qml: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only 3 | 4 | import QtTest 5 | import QtTextToSpeech 6 | 7 | TestCase { 8 | id: testCase 9 | name: "Voice" 10 | 11 | TextToSpeech { 12 | id: tts 13 | engine: "mock" 14 | } 15 | 16 | // verifies that the mock engine is synchronous 17 | function initTestCase() { 18 | compare(tts.state, TextToSpeech.Ready) 19 | } 20 | 21 | // basic API test of the voice type and Voice namespace 22 | function test_default_voice() { 23 | compare(tts.voice.name, "Bob") 24 | compare(tts.voice.age, Voice.Adult) 25 | compare(tts.voice.gender, Voice.Male) 26 | compare(tts.voice.locale, Qt.locale("en-GB")) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dist/changes-5.11.3: -------------------------------------------------------------------------------- 1 | Qt 5.11.3 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.11.0 through 5.11.2. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | http://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.11 series is binary compatible with the 5.10.x series. 10 | Applications compiled for 5.10 will continue to run with 5.11. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | - This release contains only minor code improvements. 21 | -------------------------------------------------------------------------------- /dist/changes-5.12.2: -------------------------------------------------------------------------------- 1 | Qt 5.12.2 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.12.0 through 5.12.1. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | https://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.12 series is binary compatible with the 5.11.x series. 10 | Applications compiled for 5.11 will continue to run with 5.12. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | - This release contains only minor code improvements. 21 | -------------------------------------------------------------------------------- /dist/changes-5.12.3: -------------------------------------------------------------------------------- 1 | Qt 5.12.3 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.12.0 through 5.12.2. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | https://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.12 series is binary compatible with the 5.11.x series. 10 | Applications compiled for 5.11 will continue to run with 5.12. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | - This release contains only minor code improvements. 21 | -------------------------------------------------------------------------------- /dist/changes-5.12.4: -------------------------------------------------------------------------------- 1 | Qt 5.12.4 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.12.0 through 5.12.3. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | https://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.12 series is binary compatible with the 5.11.x series. 10 | Applications compiled for 5.11 will continue to run with 5.12. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | - This release contains only minor code improvements. 21 | -------------------------------------------------------------------------------- /dist/changes-5.12.5: -------------------------------------------------------------------------------- 1 | Qt 5.12.5 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.12.0 through 5.12.4. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | https://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.12 series is binary compatible with the 5.11.x series. 10 | Applications compiled for 5.11 will continue to run with 5.12. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | - This release contains only minor code improvements. 21 | -------------------------------------------------------------------------------- /dist/changes-5.13.2: -------------------------------------------------------------------------------- 1 | Qt 5.13.2 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.13.0 through 5.13.1. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | https://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.13 series is binary compatible with the 5.12.x series. 10 | Applications compiled for 5.12 will continue to run with 5.13. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | - This release contains only minor code improvements. 21 | -------------------------------------------------------------------------------- /dist/changes-5.14.2: -------------------------------------------------------------------------------- 1 | Qt 5.14.2 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.14.0 through 5.14.1. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | https://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.14 series is binary compatible with the 5.13.x series. 10 | Applications compiled for 5.13 will continue to run with 5.14. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | - This release contains only minor code improvements. 21 | -------------------------------------------------------------------------------- /src/plugins/tts/android/src/qtexttospeech_android_plugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qtexttospeech_android_plugin.h" 6 | #include "qtexttospeech_android.h" 7 | 8 | QT_BEGIN_NAMESPACE 9 | 10 | Q_LOGGING_CATEGORY(lcSpeechTtsAndroid, "qt.speech.tts.android") 11 | 12 | QTextToSpeechEngine *QTextToSpeechPluginAndroid::createTextToSpeechEngine( 13 | const QVariantMap ¶meters, QObject *parent, QString *errorString) const 14 | { 15 | Q_UNUSED(errorString); 16 | QTextToSpeechEngineAndroid *android = new QTextToSpeechEngineAndroid(parameters, parent); 17 | if (android) { 18 | return android; 19 | } 20 | delete android; 21 | return 0; 22 | } 23 | 24 | QT_END_NAMESPACE 25 | -------------------------------------------------------------------------------- /src/tts/configure.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | 5 | 6 | #### Inputs 7 | 8 | 9 | 10 | #### Libraries 11 | 12 | qt_find_package(Flite PROVIDED_TARGETS Flite::Flite MODULE_NAME texttospeech QMAKE_LIB flite) 13 | qt_find_package(SpeechDispatcher PROVIDED_TARGETS SpeechDispatcher::SpeechDispatcher MODULE_NAME texttospeech QMAKE_LIB speechd) 14 | 15 | 16 | #### Tests 17 | 18 | 19 | 20 | #### Features 21 | 22 | qt_feature("flite" PRIVATE 23 | LABEL "Flite" 24 | CONDITION Flite_FOUND 25 | ) 26 | qt_feature("speechd" PUBLIC 27 | LABEL "Speech Dispatcher" 28 | AUTODETECT UNIX 29 | CONDITION SpeechDispatcher_FOUND 30 | ) 31 | qt_configure_add_summary_section(NAME "Qt TextToSpeech") 32 | qt_configure_add_summary_entry(ARGS "flite") 33 | qt_configure_add_summary_entry(ARGS "speechd") 34 | qt_configure_end_summary_section() # end of "Qt TextToSpeech" section 35 | -------------------------------------------------------------------------------- /examples/speech/hello_speak/doc/src/hellospeakex.qdoc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only 3 | 4 | /*! 5 | \example hello_speak 6 | \title Hello Speak Example 7 | \examplecategory {Data Processing & I/O} 8 | \ingroup qttexttospeech_examples 9 | \meta tags {widgets} 10 | 11 | \brief The Hello Speak example reads out user-provided text. 12 | 13 | The \e{Hello Speak} example demonstrates how QTextToSpeech can be used in 14 | a Qt C++ application to read out text, and to control the speech. 15 | 16 | The example uses a \l{Qt Widgets}{widget UI} to provide controls for the pitch, 17 | volume, and rate of the speech. It also lets the user select an engine, 18 | the language, and a voice. 19 | 20 | \image hellospeak-example.png {Screenshot showing a tool for text to speech 21 | with options to change volume, rate, pitch, engine language and reader 22 | voice} 23 | */ 24 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # Generated from qtspeech.pro. 5 | 6 | cmake_minimum_required(VERSION 3.16) 7 | 8 | include(.cmake.conf) 9 | project(QtSpeech 10 | VERSION "${QT_REPO_MODULE_VERSION}" 11 | DESCRIPTION "Qt Speech Libraries" 12 | HOMEPAGE_URL "https://qt.io/" 13 | LANGUAGES CXX C 14 | ) 15 | 16 | find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals) 17 | 18 | # This should be called as early as possible, just after find_package(BuildInternals) where it is 19 | # defined. 20 | qt_internal_project_setup() 21 | 22 | find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS Core) 23 | find_package(Qt6 ${PROJECT_VERSION} CONFIG OPTIONAL_COMPONENTS Gui Multimedia Widgets Test QuickTest 24 | Qml) 25 | 26 | if(NOT TARGET Qt6::Multimedia) 27 | message(NOTICE "Skipping the build as the condition \"TARGET Qt6::Multimedia\" is not met.") 28 | return() 29 | endif() 30 | 31 | qt_build_repo() 32 | -------------------------------------------------------------------------------- /examples/speech/hello_speak/mainwindow.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause 3 | 4 | #ifndef MAINWINDOW_H 5 | #define MAINWINDOW_H 6 | 7 | #include "ui_mainwindow.h" 8 | 9 | #include 10 | #include 11 | 12 | class MainWindow : public QMainWindow 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit MainWindow(QWidget *parent = nullptr); 17 | ~MainWindow(); 18 | 19 | public slots: 20 | void setRate(int); 21 | void setPitch(int); 22 | void setVolume(int volume); 23 | 24 | void stateChanged(QTextToSpeech::State state); 25 | void engineSelected(int index); 26 | void languageSelected(int language); 27 | void voiceSelected(int index); 28 | 29 | void localeChanged(const QLocale &locale); 30 | 31 | private: 32 | void onEngineReady(); 33 | 34 | Ui::MainWindow ui; 35 | QTextToSpeech *m_speech = nullptr; 36 | QList m_voices; 37 | }; 38 | 39 | #endif // MAINWINDOW_H 40 | -------------------------------------------------------------------------------- /dist/changes-5.11.2: -------------------------------------------------------------------------------- 1 | Qt 5.11.2 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.11.0 through 5.11.1. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | http://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.11 series is binary compatible with the 5.10.x series. 10 | Applications compiled for 5.10 will continue to run with 5.11. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | **************************************************************************** 21 | * Qt 5.11.2 Changes * 22 | **************************************************************************** 23 | 24 | - This release contains only minor code improvements. 25 | -------------------------------------------------------------------------------- /src/plugins/tts/speechdispatcher/qtexttospeech_speechd_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHPLUGIN_SPEECHD_H 6 | #define QTEXTTOSPEECHPLUGIN_SPEECHD_H 7 | 8 | #include "qtexttospeechplugin.h" 9 | #include "qtexttospeechengine.h" 10 | 11 | #include 12 | 13 | QT_BEGIN_NAMESPACE 14 | 15 | class QTextToSpeechSpeechdPlugin : public QObject, public QTextToSpeechPlugin 16 | { 17 | Q_OBJECT 18 | Q_INTERFACES(QTextToSpeechPlugin) 19 | Q_PLUGIN_METADATA(IID "org.qt-project.qt.speech.tts.plugin/6.0" 20 | FILE "speechd_plugin.json") 21 | 22 | public: 23 | QTextToSpeechEngine *createTextToSpeechEngine( 24 | const QVariantMap ¶meters, 25 | QObject *parent, 26 | QString *errorString) const override; 27 | }; 28 | 29 | QT_END_NAMESPACE 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/plugins/tts/mock/qtexttospeech_mock_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHPLUGIN_MOCK_H 6 | #define QTEXTTOSPEECHPLUGIN_MOCK_H 7 | 8 | #include "qtexttospeechplugin.h" 9 | #include "qtexttospeechengine.h" 10 | 11 | #include 12 | #include 13 | 14 | QT_BEGIN_NAMESPACE 15 | 16 | class QTextToSpeechMockPlugin : public QObject, public QTextToSpeechPlugin 17 | { 18 | Q_OBJECT 19 | Q_INTERFACES(QTextToSpeechPlugin) 20 | Q_PLUGIN_METADATA(IID "org.qt-project.qt.speech.tts.plugin/6.0" 21 | FILE "mock_plugin.json") 22 | 23 | public: 24 | QTextToSpeechEngine *createTextToSpeechEngine( 25 | const QVariantMap ¶meters, 26 | QObject *parent, 27 | QString *errorString) const override; 28 | }; 29 | 30 | QT_END_NAMESPACE 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /examples/speech/hello_speak/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause 3 | 4 | cmake_minimum_required(VERSION 3.14) 5 | project(hello_speak LANGUAGES CXX) 6 | 7 | if(NOT DEFINED INSTALL_EXAMPLESDIR) 8 | set(INSTALL_EXAMPLESDIR "examples") 9 | endif() 10 | 11 | set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/speech/hello_speak") 12 | 13 | find_package(Qt6 REQUIRED COMPONENTS Core Gui TextToSpeech Widgets) 14 | 15 | qt_standard_project_setup() 16 | 17 | qt_add_executable(hello_speak 18 | main.cpp 19 | mainwindow.cpp mainwindow.h mainwindow.ui 20 | ) 21 | 22 | set_target_properties(hello_speak PROPERTIES 23 | WIN32_EXECUTABLE TRUE 24 | MACOSX_BUNDLE TRUE 25 | ) 26 | 27 | target_link_libraries(hello_speak PRIVATE 28 | Qt6::Core 29 | Qt6::Gui 30 | Qt6::TextToSpeech 31 | Qt6::Widgets 32 | ) 33 | 34 | install(TARGETS hello_speak 35 | RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" 36 | BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" 37 | LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" 38 | ) 39 | -------------------------------------------------------------------------------- /src/plugins/tts/sapi/qtexttospeech_sapi_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHPLUGIN_SAPI_H 6 | #define QTEXTTOSPEECHPLUGIN_SAPI_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | QT_BEGIN_NAMESPACE 14 | 15 | class QTextToSpeechSapiPlugin : public QObject, public QTextToSpeechPlugin 16 | { 17 | Q_OBJECT 18 | Q_INTERFACES(QTextToSpeechPlugin) 19 | Q_PLUGIN_METADATA(IID "org.qt-project.qt.speech.tts.plugin/6.0" 20 | FILE "sapi_plugin.json") 21 | 22 | public: 23 | QTextToSpeechEngine *createTextToSpeechEngine( 24 | const QVariantMap ¶meters, 25 | QObject *parent, 26 | QString *errorString) const override; 27 | }; 28 | 29 | QT_END_NAMESPACE 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/plugins/tts/winrt/qtexttospeech_winrt_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHPLUGIN_WINRT_H 6 | #define QTEXTTOSPEECHPLUGIN_WINRT_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | QT_BEGIN_NAMESPACE 14 | 15 | class QTextToSpeechWinRTPlugin : public QObject, public QTextToSpeechPlugin 16 | { 17 | Q_OBJECT 18 | Q_INTERFACES(QTextToSpeechPlugin) 19 | Q_PLUGIN_METADATA(IID "org.qt-project.qt.speech.tts.plugin/6.0" 20 | FILE "winrt_plugin.json") 21 | 22 | public: 23 | QTextToSpeechEngine *createTextToSpeechEngine( 24 | const QVariantMap ¶meters, 25 | QObject *parent, 26 | QString *errorString) const override; 27 | }; 28 | 29 | QT_END_NAMESPACE 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/plugins/tts/darwin/qtexttospeech_darwin_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHPLUGIN_DARWIN_H 6 | #define QTEXTTOSPEECHPLUGIN_DARWIN_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | QT_BEGIN_NAMESPACE 14 | 15 | class QTextToSpeechDarwinPlugin : public QObject, public QTextToSpeechPlugin 16 | { 17 | Q_OBJECT 18 | Q_INTERFACES(QTextToSpeechPlugin) 19 | Q_PLUGIN_METADATA(IID "org.qt-project.qt.speech.tts.plugin/6.0" 20 | FILE "darwin_plugin.json") 21 | 22 | public: 23 | QTextToSpeechEngine *createTextToSpeechEngine( 24 | const QVariantMap ¶meters, 25 | QObject *parent, 26 | QString *errorString) const override; 27 | }; 28 | 29 | QT_END_NAMESPACE 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/plugins/tts/flite/qtexttospeech_flite_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHPLUGIN_FLITE_H 6 | #define QTEXTTOSPEECHPLUGIN_FLITE_H 7 | 8 | #include "qtexttospeechplugin.h" 9 | #include "qtexttospeechengine.h" 10 | 11 | #include 12 | #include 13 | 14 | QT_BEGIN_NAMESPACE 15 | 16 | Q_DECLARE_LOGGING_CATEGORY(lcSpeechTtsFlite) 17 | 18 | class QTextToSpeechFlitePlugin : public QObject, public QTextToSpeechPlugin 19 | { 20 | Q_OBJECT 21 | Q_INTERFACES(QTextToSpeechPlugin) 22 | Q_PLUGIN_METADATA(IID "org.qt-project.qt.speech.tts.plugin/6.0" 23 | FILE "flite_plugin.json") 24 | 25 | public: 26 | QTextToSpeechEngine *createTextToSpeechEngine( 27 | const QVariantMap ¶meters, 28 | QObject *parent, 29 | QString *errorString) const override; 30 | }; 31 | 32 | QT_END_NAMESPACE 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/plugins/tts/android/src/qtexttospeech_android_plugin.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHPLUGIN_ANDROID_H 6 | #define QTEXTTOSPEECHPLUGIN_ANDROID_H 7 | 8 | #include "qtexttospeechplugin.h" 9 | #include "qtexttospeechengine.h" 10 | 11 | #include 12 | #include 13 | 14 | QT_BEGIN_NAMESPACE 15 | 16 | Q_DECLARE_LOGGING_CATEGORY(lcSpeechTtsAndroid) 17 | 18 | class QTextToSpeechPluginAndroid : public QObject, public QTextToSpeechPlugin 19 | { 20 | Q_OBJECT 21 | Q_INTERFACES(QTextToSpeechPlugin) 22 | Q_PLUGIN_METADATA(IID "org.qt-project.qt.speech.tts.plugin/6.0" 23 | FILE "android_plugin.json") 24 | 25 | public: 26 | QTextToSpeechEngine *createTextToSpeechEngine( 27 | const QVariantMap ¶meters, 28 | QObject *parent, 29 | QString *errorString) const override; 30 | }; 31 | 32 | QT_END_NAMESPACE 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/tts/qml/qtexttospeech_qmltypes_p.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTTEXTTOSPEECHTYPES_H 6 | #define QTTEXTTOSPEECHTYPES_H 7 | 8 | // 9 | // W A R N I N G 10 | // ------------- 11 | // 12 | // This file is not part of the Qt API. It exists purely as an 13 | // implementation detail. This header file may change from version to 14 | // version without notice, or even be removed. 15 | // 16 | // We mean it. 17 | // 18 | 19 | #include 20 | #include 21 | 22 | QT_BEGIN_NAMESPACE 23 | 24 | struct QVoiceForeign 25 | { 26 | Q_GADGET 27 | QML_FOREIGN(QVoice) 28 | QML_VALUE_TYPE(voice) 29 | }; 30 | 31 | // To prevent the same QVoice type from being exported twice into qmltypes 32 | // (for value type and for the enums) 33 | struct QVoiceDerived : public QVoice 34 | { 35 | Q_GADGET 36 | }; 37 | 38 | namespace QVoiceForeignNamespace 39 | { 40 | Q_NAMESPACE 41 | QML_FOREIGN_NAMESPACE(QVoiceDerived) 42 | QML_NAMED_ELEMENT(Voice) 43 | } 44 | 45 | QT_END_NAMESPACE 46 | 47 | #endif // QTTEXTTOSPEECHTYPES_H 48 | -------------------------------------------------------------------------------- /src/tts/qtexttospeechplugin.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHPLUGIN_H 6 | #define QTEXTTOSPEECHPLUGIN_H 7 | 8 | // 9 | // W A R N I N G 10 | // ------------- 11 | // 12 | // This file is part of the Qt TextToSpeech plugin API, with limited compatibility 13 | // guarantees. 14 | // Usage of this API may make your code source and binary incompatible with 15 | // future versions of Qt. 16 | // 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | QT_BEGIN_NAMESPACE 25 | 26 | class Q_TEXTTOSPEECH_EXPORT QTextToSpeechPlugin 27 | { 28 | public: 29 | virtual ~QTextToSpeechPlugin() {} 30 | 31 | virtual QTextToSpeechEngine *createTextToSpeechEngine( 32 | const QVariantMap ¶meters, 33 | QObject *parent, 34 | QString *errorString) const; 35 | }; 36 | 37 | Q_DECLARE_INTERFACE(QTextToSpeechPlugin, 38 | "org.qt-project.qt.speech.tts.plugin/6.0") 39 | 40 | QT_END_NAMESPACE 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/tts/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | qt_internal_add_module(TextToSpeech 5 | PLUGIN_TYPES texttospeech 6 | SOURCES 7 | qtexttospeech.cpp qtexttospeech.h qtexttospeech_p.h 8 | qtexttospeech_global.h 9 | qtexttospeechengine.cpp qtexttospeechengine.h 10 | qtexttospeechplugin.cpp qtexttospeechplugin.h 11 | qvoice.cpp qvoice.h qvoice_p.h 12 | DEFINES 13 | QTEXTTOSPEECH_LIBRARY 14 | QT_NO_CONTEXTLESS_CONNECT 15 | LIBRARIES 16 | Qt::CorePrivate 17 | PUBLIC_LIBRARIES 18 | Qt::Core 19 | Qt::Multimedia 20 | PRIVATE_MODULE_INTERFACE 21 | Qt::CorePrivate 22 | NO_GENERATE_CPP_EXPORTS 23 | ) 24 | 25 | 26 | if(TARGET Qt::Qml) 27 | add_subdirectory(qml) 28 | endif() 29 | 30 | if(ANDROID) 31 | set_property(TARGET TextToSpeech APPEND PROPERTY QT_ANDROID_BUNDLED_JAR_DEPENDENCIES 32 | jar/QtAndroidTextToSpeech.jar 33 | ) 34 | set_property(TARGET TextToSpeech APPEND PROPERTY QT_ANDROID_LIB_DEPENDENCIES 35 | ${INSTALL_PLUGINSDIR}/texttospeech/libplugins_texttospeech_qttexttospeech_android.so 36 | ) 37 | endif() 38 | 39 | qt_internal_add_docs(TextToSpeech 40 | doc/qttexttospeech.qdocconf 41 | ) 42 | -------------------------------------------------------------------------------- /coin/axivion/ci_config_linux.json: -------------------------------------------------------------------------------- 1 | { 2 | "Project": { 3 | "BuildSystemIntegration": { 4 | "child_order": [ 5 | "GCCSetup", 6 | "CMake", 7 | "LinkLibraries" 8 | ] 9 | }, 10 | "CMake": { 11 | "_active": true, 12 | "_copy_from": "CMakeIntegration", 13 | "build_environment": {}, 14 | "build_options": "-j4", 15 | "generate_options": "--fresh", 16 | "generator": "Ninja" 17 | }, 18 | "GCCSetup": { 19 | "_active": true, 20 | "_copy_from": "Command", 21 | "build_command": "gccsetup --cc gcc --cxx g++ --config ../../../axivion/" 22 | }, 23 | "LinkLibraries": { 24 | "_active": true, 25 | "_copy_from": "AxivionLinker", 26 | "input_files": [ 27 | "build/lib/lib*.so*.ir", 28 | "build/qml/*/lib*.so*.ir" 29 | ], 30 | "ir": "build/$(env:TESTED_MODULE_COIN).ir", 31 | "plugin_files": [ 32 | "build/plugins/*/lib*.so*.ir" 33 | ] 34 | } 35 | }, 36 | "_Format": "1.0", 37 | "_Version": "7.6.2", 38 | "_VersionNum": [ 39 | 7, 40 | 6, 41 | 2, 42 | 12725 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /examples/speech/quickspeech/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2023 The Qt Company Ltd. 2 | # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause 3 | 4 | cmake_minimum_required(VERSION 3.16) 5 | project(quickspeech VERSION 0.1 LANGUAGES CXX) 6 | 7 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 8 | 9 | if(NOT DEFINED INSTALL_EXAMPLESDIR) 10 | set(INSTALL_EXAMPLESDIR "examples") 11 | endif() 12 | 13 | set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/speech/quickspeech") 14 | 15 | find_package(Qt6 REQUIRED COMPONENTS Quick TextToSpeech) 16 | 17 | qt_standard_project_setup(REQUIRES 6.5) 18 | 19 | qt_add_executable(quickspeech 20 | main.cpp 21 | ) 22 | 23 | qt_add_qml_module(quickspeech 24 | URI main 25 | VERSION 1.0 26 | QML_FILES "Main.qml" 27 | ) 28 | 29 | set_target_properties(quickspeech PROPERTIES 30 | MACOSX_BUNDLE_GUI_IDENTIFIER my.example.com 31 | MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION} 32 | MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR} 33 | MACOSX_BUNDLE TRUE 34 | WIN32_EXECUTABLE TRUE 35 | ) 36 | 37 | target_link_libraries(quickspeech PRIVATE 38 | Qt6::Quick 39 | Qt6::TextToSpeech 40 | ) 41 | 42 | install(TARGETS quickspeech 43 | RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" 44 | BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" 45 | LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" 46 | ) 47 | -------------------------------------------------------------------------------- /dist/changes-5.11.1: -------------------------------------------------------------------------------- 1 | Qt 5.11.1 is a bug-fix release. It maintains both forward and backward 2 | compatibility (source and binary) with Qt 5.11.0. 3 | 4 | For more details, refer to the online documentation included in this 5 | distribution. The documentation is also available online: 6 | 7 | http://doc.qt.io/qt-5/index.html 8 | 9 | The Qt version 5.11 series is binary compatible with the 5.10.x series. 10 | Applications compiled for 5.10 will continue to run with 5.11. 11 | 12 | Some of the changes listed in this file include issue tracking numbers 13 | corresponding to tasks in the Qt Bug Tracker: 14 | 15 | https://bugreports.qt.io/ 16 | 17 | Each of these identifiers can be entered in the bug tracker to obtain more 18 | information about a particular change. 19 | 20 | **************************************************************************** 21 | * Qt 5.11.1 Changes * 22 | **************************************************************************** 23 | 24 | **************************************************************************** 25 | * UNSPECIFIED * 26 | **************************************************************************** 27 | 28 | - [QTBUG-66209] Fixed type of volume property, it has to be double, not 29 | int, to be the same as in the related functions (the volumeChanged signal 30 | was overloaded, the type of the property was fixed). 31 | -------------------------------------------------------------------------------- /LICENSES/BSD-3-Clause.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) . 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 7 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /src/tts/qtexttospeechplugin.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qtexttospeechplugin.h" 6 | 7 | QT_BEGIN_NAMESPACE 8 | 9 | /*! 10 | \class QTextToSpeechPlugin 11 | \inmodule QtTextToSpeech 12 | \brief The QTextToSpeechPlugin class is the base for all text-to-speech plug-ins. 13 | \internal 14 | 15 | A plug-in implementation should derive from QTextToSpeechPlugin and re-implement 16 | \l createTextToSpeechEngine(). 17 | */ 18 | 19 | /*! 20 | Factory method that is triggered by a call to \l QTextToSpeech::QTextToSpeech() 21 | when a provider name is given in the constructor and a text-to-speech plug-in 22 | matching the provider name was successfully loaded. 23 | 24 | Value of \a parameters is currently always empty. 25 | 26 | If an error occurs, the method should return 0 and (optionally) give a description 27 | of the error in \a errorString. In this case, QTextToSpeech::state() will return 28 | QTextToSpeech::Error. 29 | 30 | If \a parent is 0, the caller takes the ownership of the returned engine instance. 31 | */ 32 | QTextToSpeechEngine *QTextToSpeechPlugin::createTextToSpeechEngine( 33 | const QVariantMap ¶meters, 34 | QObject *parent, 35 | QString *errorString) const 36 | { 37 | Q_UNUSED(parameters); 38 | Q_UNUSED(parent); 39 | Q_UNUSED(errorString); 40 | 41 | return 0; 42 | } 43 | 44 | QT_END_NAMESPACE 45 | -------------------------------------------------------------------------------- /src/tts/qvoice_p.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QVOICE_P_H 6 | #define QVOICE_P_H 7 | 8 | // 9 | // W A R N I N G 10 | // ------------- 11 | // 12 | // This file is not part of the Qt API. It exists for the convenience 13 | // of other Qt classes. This header file may change from version to 14 | // version without notice, or even be removed. 15 | // 16 | // We mean it. 17 | // 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | QT_BEGIN_NAMESPACE 27 | 28 | class QVoicePrivate : public QSharedData 29 | { 30 | public: 31 | QVoicePrivate() = default; 32 | QVoicePrivate(const QVoicePrivate &other); 33 | QVoicePrivate(const QString &n, const QLocale &l, QVoice::Gender g, 34 | QVoice::Age a, const QVariant &d); 35 | ~QVoicePrivate() = default; 36 | 37 | QString name; 38 | QLocale locale; 39 | QVoice::Gender gender = QVoice::Unknown; 40 | QVoice::Age age = QVoice::Other; 41 | // Various data depending on the platform: 42 | // On OS X the VoiceIdentifier is stored. 43 | // On unix the synthesizer (output module) is stored. 44 | QVariant data; 45 | }; 46 | 47 | QVoicePrivate::QVoicePrivate(const QVoicePrivate &other) 48 | : QSharedData(other), name(other.name), locale(other.locale) 49 | , gender(other.gender), age(other.age), data(other.data) 50 | { 51 | } 52 | 53 | QVoicePrivate::QVoicePrivate(const QString &n, const QLocale &l, QVoice::Gender g, 54 | QVoice::Age a, const QVariant &d) 55 | :name(n), locale(l), gender(g), age(a), data(d) 56 | { 57 | } 58 | 59 | QT_END_NAMESPACE 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /src/tts/qml/qvoiceselector_p.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QVOICESELECTOR_H 6 | #define QVOICESELECTOR_H 7 | 8 | // 9 | // W A R N I N G 10 | // ------------- 11 | // 12 | // This file is not part of the Qt API. It exists purely as an 13 | // implementation detail. This header file may change from version to 14 | // version without notice, or even be removed. 15 | // 16 | // We mean it. 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | QT_BEGIN_NAMESPACE 25 | 26 | struct QVoiceSelector 27 | { 28 | Q_GADGET 29 | QML_VALUE_TYPE(voiceSelector) 30 | QML_STRUCTURED_VALUE 31 | 32 | Q_PROPERTY(QRegularExpression name READ name WRITE setName); 33 | Q_PROPERTY(QLocale locale READ locale WRITE setLocale); 34 | Q_PROPERTY(QVoice::Age age READ age WRITE setAge); 35 | Q_PROPERTY(QVoice::Gender gender READ gender WRITE setGender); 36 | 37 | public: 38 | QRegularExpression name() const { return m_name; } 39 | void setName(const QRegularExpression &name) { m_name = name; } 40 | QLocale locale() const { return m_locale; } 41 | void setLocale(const QLocale &locale) { m_locale = locale; } 42 | QVoice::Age age() const { return m_age; } 43 | void setAge(QVoice::Age age) { m_age = age; } 44 | QVoice::Gender gender() const { return m_gender; } 45 | void setGender(QVoice::Gender gender) { m_gender = gender; } 46 | 47 | QRegularExpression m_name; 48 | QLocale m_locale = QLocale::C; 49 | QVoice::Age m_age = QVoice::Age(-1); 50 | QVoice::Gender m_gender = QVoice::Gender(-1); 51 | }; 52 | 53 | QT_END_NAMESPACE 54 | 55 | #endif // QVOICESELECTOR_H 56 | -------------------------------------------------------------------------------- /src/plugins/tts/winrt/qtexttospeech_winrt.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHENGINE_WINRT_H 6 | #define QTEXTTOSPEECHENGINE_WINRT_H 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | QT_BEGIN_NAMESPACE 17 | 18 | class QAudioDevice; 19 | class QTextToSpeechEngineWinRTPrivate; 20 | 21 | class QTextToSpeechEngineWinRT : public QTextToSpeechEngine 22 | { 23 | Q_OBJECT 24 | 25 | public: 26 | QTextToSpeechEngineWinRT(const QVariantMap ¶meters, QObject *parent); 27 | ~QTextToSpeechEngineWinRT(); 28 | 29 | QList availableLocales() const override; 30 | QList availableVoices() const override; 31 | void say(const QString &text) override; 32 | void synthesize(const QString &text) override; 33 | void stop(QTextToSpeech::BoundaryHint boundaryHint) override; 34 | void pause(QTextToSpeech::BoundaryHint boundaryHint) override; 35 | void resume() override; 36 | double rate() const override; 37 | bool setRate(double rate) override; 38 | double pitch() const override; 39 | bool setPitch(double pitch) override; 40 | QLocale locale() const override; 41 | bool setLocale(const QLocale &locale) override; 42 | double volume() const override; 43 | bool setVolume(double volume) override; 44 | QVoice voice() const override; 45 | bool setVoice(const QVoice &voice) override; 46 | QTextToSpeech::State state() const override; 47 | QTextToSpeech::ErrorReason errorReason() const override; 48 | QString errorString() const override; 49 | 50 | protected: 51 | void timerEvent(QTimerEvent *e) override; 52 | 53 | private: 54 | QScopedPointer d_ptr; 55 | Q_DECLARE_PRIVATE(QTextToSpeechEngineWinRT) 56 | }; 57 | 58 | QT_END_NAMESPACE 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/tts/qml/qdeclarativetexttospeech_p.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QDECLARATIVETEXTTOSPEECH_H 6 | #define QDECLARATIVETEXTTOSPEECH_H 7 | 8 | // 9 | // W A R N I N G 10 | // ------------- 11 | // 12 | // This file is not part of the Qt API. It exists purely as an 13 | // implementation detail. This header file may change from version to 14 | // version without notice, or even be removed. 15 | // 16 | // We mean it. 17 | // 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | QT_BEGIN_NAMESPACE 25 | 26 | class QVoiceSelectorAttached; 27 | 28 | class QDeclarativeTextToSpeech : public QTextToSpeech, public QQmlParserStatus 29 | { 30 | Q_OBJECT 31 | Q_PROPERTY(QString engine READ engine WRITE setEngine NOTIFY engineChanged FINAL) 32 | Q_PROPERTY(QVariantMap engineParameters READ engineParameters WRITE setEngineParameters NOTIFY engineParametersChanged REVISION(6, 6) FINAL) 33 | 34 | Q_INTERFACES(QQmlParserStatus) 35 | QML_NAMED_ELEMENT(TextToSpeech) 36 | 37 | public: 38 | explicit QDeclarativeTextToSpeech(QObject *parent = nullptr); 39 | 40 | Q_REVISION(6, 6) Q_INVOKABLE QList findVoices(const QVariantMap &criteria) const; 41 | 42 | QVoiceSelectorAttached *m_voiceSelector = nullptr; 43 | 44 | void selectVoice(); 45 | 46 | QString engine() const; 47 | void setEngine(const QString &engine); 48 | 49 | QVariantMap engineParameters() const; 50 | void setEngineParameters(const QVariantMap ¶meters); 51 | 52 | Q_SIGNALS: 53 | void engineChanged(const QString &); 54 | Q_REVISION(6, 6) void engineParametersChanged(); 55 | 56 | protected: 57 | void classBegin() override; 58 | void componentComplete() override; 59 | 60 | private: 61 | bool m_complete = false; 62 | QString m_engine; 63 | QVariantMap m_engineParameters; 64 | }; 65 | 66 | QT_END_NAMESPACE 67 | 68 | #endif // QDECLARATIVETEXTTOSPEECH_H 69 | -------------------------------------------------------------------------------- /src/tts/qtexttospeech_p.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECH_P_H 6 | #define QTEXTTOSPEECH_P_H 7 | 8 | // 9 | // W A R N I N G 10 | // ------------- 11 | // 12 | // This file is not part of the Qt API. It exists for the convenience 13 | // of other Qt classes. This header file may change from version to 14 | // version without notice, or even be removed. 15 | // 16 | // We mean it. 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | QT_BEGIN_NAMESPACE 29 | 30 | class QTextToSpeech; 31 | class QTextToSpeechPrivate : public QObjectPrivate 32 | { 33 | Q_DECLARE_PUBLIC(QTextToSpeech) 34 | public: 35 | QTextToSpeechPrivate(QTextToSpeech *speech); 36 | ~QTextToSpeechPrivate(); 37 | 38 | void setEngineProvider(const QString &engine, const QVariantMap ¶ms); 39 | static QMultiHash plugins(bool reload = false); 40 | 41 | private: 42 | bool loadMeta(); 43 | void loadPlugin(); 44 | void updateState(QTextToSpeech::State newState); 45 | void disconnectSynthesizeFunctor(); 46 | static void loadPluginMetadata(QMultiHash &list); 47 | QTextToSpeech *q_ptr; 48 | QTextToSpeechPlugin *m_plugin = nullptr; 49 | std::unique_ptr m_engine = nullptr; 50 | QString m_providerName; 51 | QCborMap m_metaData; 52 | static QMutex m_mutex; 53 | QQueue m_pendingUtterances; 54 | QTextToSpeech::State m_state = QTextToSpeech::Error; 55 | QMetaObject::Connection m_synthesizeConnection; 56 | QtPrivate::QSlotObjectBase *m_slotObject = nullptr; 57 | 58 | qsizetype m_utteranceCounter = 0; 59 | qsizetype m_currentUtterance = 0; 60 | double m_storedPitch = qQNaN(); 61 | double m_storedVolume = qQNaN(); 62 | double m_storedRate = qQNaN(); 63 | }; 64 | 65 | QT_END_NAMESPACE 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /REUSE.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[annotations]] 4 | path = ["src/tts/doc/QtTextToSpeechDoc", 5 | "src/plugins/tts/android/jar/AndroidManifest.xml", 6 | "src/plugins/**json"] 7 | precedence = "closest" 8 | comment = "src and plugin" 9 | SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." 10 | SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only" 11 | 12 | [[annotations]] 13 | path = ["**CMakeLists.txt", ".cmake.conf", "**.yaml", "**configure.json", 14 | "qt_cmdline.cmake", "**BLACKLIST", "**ci_config_linux.json", ".tag"] 15 | precedence = "closest" 16 | comment = "build system" 17 | SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." 18 | SPDX-License-Identifier = "BSD-3-Clause" 19 | 20 | [[annotations]] 21 | path = ["**/.gitattributes", "**.gitignore", "**.gitreview"] 22 | precedence = "closest" 23 | comment = "version control system. Infrastruture" 24 | SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." 25 | SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" 26 | 27 | [[annotations]] 28 | path = ["examples/**"] 29 | comment = "this must be after the build system table because example and snippets take precedence over build system" 30 | precedence = "closest" 31 | SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." 32 | SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" 33 | 34 | [[annotations]] 35 | path = ["**/doc/images/**", "**.qdocconf", "config_help.txt"] 36 | comment = "documentation" 37 | precedence = "closest" 38 | SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." 39 | SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only" 40 | 41 | [[annotations]] 42 | path = ["**.toml", "licenseRule.json"] 43 | comment = "infrastructure" 44 | precedence = "override" 45 | SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." 46 | SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" 47 | 48 | [[annotations]] 49 | path = ["**/qt_attribution.json"] 50 | comment = "documentation" 51 | precedence = "override" 52 | SPDX-FileCopyrightText = "Copyright (C) The Qt Company Ltd." 53 | SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only" 54 | -------------------------------------------------------------------------------- /src/plugins/tts/mock/qtexttospeech_mock.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECH_MOCK_H 6 | #define QTEXTTOSPEECH_MOCK_H 7 | 8 | #include "qtexttospeechengine.h" 9 | #include 10 | 11 | QT_BEGIN_NAMESPACE 12 | 13 | class QTextToSpeechEngineMock : public QTextToSpeechEngine 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit QTextToSpeechEngineMock(const QVariantMap ¶meters, QObject *parent = nullptr); 19 | ~QTextToSpeechEngineMock(); 20 | 21 | QList availableLocales() const override; 22 | QList availableVoices() const override; 23 | 24 | void say(const QString &text) override; 25 | void synthesize(const QString &text) override; 26 | void stop(QTextToSpeech::BoundaryHint boundaryHint) override; 27 | void pause(QTextToSpeech::BoundaryHint boundaryHint) override; 28 | void resume() override; 29 | 30 | double rate() const override; 31 | bool setRate(double rate) override; 32 | double pitch() const override; 33 | bool setPitch(double pitch) override; 34 | QLocale locale() const override; 35 | bool setLocale(const QLocale &locale) override; 36 | double volume() const override; 37 | bool setVolume(double volume) override; 38 | QVoice voice() const override; 39 | bool setVoice(const QVoice &voice) override; 40 | QTextToSpeech::State state() const override; 41 | QTextToSpeech::ErrorReason errorReason() const override; 42 | QString errorString() const override; 43 | 44 | protected: 45 | void timerEvent(QTimerEvent *e) override; 46 | 47 | private: 48 | // mock engine uses 100ms per word, +/- 50ms depending on rate 49 | int wordTime() const { return 100 - int(50.0 * m_rate); } 50 | 51 | const QVariantMap m_parameters; 52 | QString m_text; 53 | QLocale m_locale; 54 | QVoice m_voice; 55 | QBasicTimer m_timer; 56 | double m_rate = 0.0; 57 | double m_pitch = 0.0; 58 | double m_volume = 0.5; 59 | QTextToSpeech::State m_state = QTextToSpeech::Error; 60 | QTextToSpeech::ErrorReason m_errorReason = QTextToSpeech::ErrorReason::Initialization; 61 | QString m_errorString; 62 | bool m_pauseRequested = false; 63 | qsizetype m_currentIndex = -1; 64 | QAudioFormat m_format; 65 | }; 66 | 67 | QT_END_NAMESPACE 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/tts/configure.json: -------------------------------------------------------------------------------- 1 | { 2 | "module": "texttospeech", 3 | "depends": [ 4 | "gui" 5 | ], 6 | 7 | "commandline": { 8 | "options": { 9 | "flite": "boolean", 10 | "flite-alsa": { "type": "boolean", "name": "flite_alsa" }, 11 | "speechd": "boolean" 12 | } 13 | }, 14 | 15 | "libraries": { 16 | "flite": { 17 | "label": "Flite", 18 | "test": { 19 | "include": "flite/flite.h", 20 | "tail": [ 21 | "static int fliteAudioCb(const cst_wave *, int, int, int, cst_audio_streaming_info *)", 22 | "{ return CST_AUDIO_STREAM_STOP; }" 23 | ], 24 | "main": [ 25 | "cst_audio_streaming_info *asi = new_audio_streaming_info();", 26 | "asi->asc = fliteAudioCb; // This fails for old Flite", 27 | "new_audio_streaming_info();" 28 | ] 29 | }, 30 | "sources": [ 31 | "-lflite_cmu_us_kal16 -lflite_usenglish -lflite_cmulex -lflite" 32 | ] 33 | }, 34 | "speechd": { 35 | "label": "Speech Dispatcher", 36 | "test": { 37 | "include": "libspeechd.h", 38 | "main": [ 39 | "spd_close(spd_open(\"QtConfigTest\", \"main\", 0, SPD_MODE_THREADED));" 40 | ] 41 | }, 42 | "sources": [ 43 | { "type": "pkgConfig", "args": "speech-dispatcher" }, 44 | "-lspeechd" 45 | ] 46 | } 47 | }, 48 | 49 | "features": { 50 | "flite": { 51 | "label": "Flite", 52 | "condition": "libs.flite", 53 | "output": [ "privateFeature" ] 54 | }, 55 | "flite_alsa": { 56 | "label": "Flite with ALSA", 57 | "condition": "libs.flite && libs.flite_alsa", 58 | "output": [ "privateFeature" ] 59 | }, 60 | "speechd": { 61 | "label": "Speech Dispatcher", 62 | "autoDetect": "config.unix", 63 | "condition": "libs.speechd", 64 | "output": [ "publicFeature" ] 65 | } 66 | }, 67 | 68 | "summary": [ 69 | { 70 | "section": "Qt TextToSpeech", 71 | "entries": [ 72 | "flite", 73 | "flite_alsa", 74 | "speechd" 75 | ] 76 | } 77 | ] 78 | } 79 | -------------------------------------------------------------------------------- /src/plugins/tts/speechdispatcher/qtexttospeech_speechd.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHENGINE_SPEECHD_H 6 | #define QTEXTTOSPEECHENGINE_SPEECHD_H 7 | 8 | #include "qtexttospeechengine.h" 9 | #include "qvoice.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | QT_BEGIN_NAMESPACE 19 | 20 | class QTextToSpeechEngineSpeechd : public QTextToSpeechEngine 21 | { 22 | Q_OBJECT 23 | 24 | public: 25 | QTextToSpeechEngineSpeechd(const QVariantMap ¶meters, QObject *parent); 26 | ~QTextToSpeechEngineSpeechd(); 27 | 28 | // Plug-in API: 29 | QList availableLocales() const override; 30 | QList availableVoices() const override; 31 | void say(const QString &text) override; 32 | void synthesize(const QString &text) override; 33 | void stop(QTextToSpeech::BoundaryHint boundaryHint) override; 34 | void pause(QTextToSpeech::BoundaryHint boundaryHint) override; 35 | void resume() override; 36 | double rate() const override; 37 | bool setRate(double rate) override; 38 | double pitch() const override; 39 | bool setPitch(double pitch) override; 40 | QLocale locale() const override; 41 | bool setLocale(const QLocale &locale) override; 42 | double volume() const override; 43 | bool setVolume(double volume) override; 44 | QVoice voice() const override; 45 | bool setVoice(const QVoice &voice) override; 46 | QTextToSpeech::State state() const override; 47 | QTextToSpeech::ErrorReason errorReason() const override; 48 | QString errorString() const override; 49 | 50 | void spdStateChanged(SPDNotificationType state); 51 | 52 | private: 53 | QLocale localeForVoice(SPDVoice *voice) const; 54 | bool connectToSpeechDispatcher(); 55 | void updateVoices(); 56 | void setError(QTextToSpeech::ErrorReason reason, const QString &errorString); 57 | 58 | QTextToSpeech::State m_state = QTextToSpeech::Error; 59 | QTextToSpeech::ErrorReason m_errorReason = QTextToSpeech::ErrorReason::Initialization; 60 | QString m_errorString; 61 | SPDConnection *speechDispatcher; 62 | QVoice m_currentVoice; 63 | // Voices mapped by their locale name. 64 | QMultiHash m_voices; 65 | }; 66 | 67 | QT_END_NAMESPACE 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/tts/qml/qvoiceselectorattached_p.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QVOICESELECTORATTACHED_H 6 | #define QVOICESELECTORATTACHED_H 7 | 8 | // 9 | // W A R N I N G 10 | // ------------- 11 | // 12 | // This file is not part of the Qt API. It exists purely as an 13 | // implementation detail. This header file may change from version to 14 | // version without notice, or even be removed. 15 | // 16 | // We mean it. 17 | // 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | QT_BEGIN_NAMESPACE 24 | 25 | class QDeclarativeTextToSpeech; 26 | 27 | class QVoiceSelectorAttached : public QObject 28 | { 29 | Q_OBJECT 30 | Q_PROPERTY(QVariant name READ name WRITE setName NOTIFY nameChanged FINAL) 31 | Q_PROPERTY(QVoice::Gender gender READ gender WRITE setGender NOTIFY genderChanged FINAL) 32 | Q_PROPERTY(QVoice::Age age READ age WRITE setAge NOTIFY ageChanged FINAL) 33 | Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged FINAL) 34 | Q_PROPERTY(QLocale language READ language WRITE setLanguage NOTIFY languageChanged FINAL) 35 | 36 | QML_NAMED_ELEMENT(VoiceSelector) 37 | QML_ADDED_IN_VERSION(6, 6) 38 | QML_UNCREATABLE("VoiceSelector is only available via attached properties.") 39 | QML_ATTACHED(QVoiceSelectorAttached) 40 | 41 | public: 42 | static QVoiceSelectorAttached *qmlAttachedProperties(QObject *obj); 43 | 44 | QVariant name() const; 45 | void setName(const QVariant &name); 46 | 47 | QVoice::Gender gender() const; 48 | void setGender(QVoice::Gender gender); 49 | 50 | QVoice::Age age() const; 51 | void setAge(QVoice::Age age); 52 | 53 | QLocale locale() const; 54 | void setLocale(const QLocale &locale); 55 | 56 | QLocale language() const; 57 | void setLanguage(const QLocale &language); 58 | 59 | QVariantMap selectionCriteria() const { return m_criteria; } 60 | 61 | public Q_SLOTS: 62 | void select(); 63 | 64 | Q_SIGNALS: 65 | void nameChanged(); 66 | void genderChanged(); 67 | void ageChanged(); 68 | void localeChanged(); 69 | void languageChanged(); 70 | 71 | private: 72 | explicit QVoiceSelectorAttached(QDeclarativeTextToSpeech *tts = nullptr); 73 | 74 | QVariantMap m_criteria; 75 | QDeclarativeTextToSpeech *m_tts; 76 | }; 77 | 78 | QT_END_NAMESPACE 79 | 80 | #endif // QVOICESELECTORATTACHED_H 81 | -------------------------------------------------------------------------------- /cmake/FindFlite.cmake: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2022 The Qt Company Ltd. 2 | # SPDX-License-Identifier: BSD-3-Clause 3 | 4 | # We can't create the same interface imported target multiple times, CMake will complain if we do 5 | # that. This can happen if the find_package call is done in multiple different subdirectories. 6 | if(TARGET Flite::Flite) 7 | set(Flite_FOUND 1) 8 | return() 9 | endif() 10 | 11 | find_path(Flite_INCLUDE_DIR 12 | NAMES 13 | flite/flite.h 14 | ) 15 | find_library(Flite_LIBRARY 16 | NAMES 17 | flite 18 | ) 19 | 20 | if(NOT Flite_INCLUDE_DIR OR NOT Flite_LIBRARY) 21 | set(Flite_FOUND 0) 22 | return() 23 | endif() 24 | 25 | include(CMakePushCheckState) 26 | include(CheckCXXSourceCompiles) 27 | 28 | # Flite can be built with ALSA support, 29 | # in which case we need to link ALSA as well 30 | find_package(ALSA QUIET) 31 | 32 | cmake_push_check_state(RESET) 33 | 34 | set(CMAKE_REQUIRED_INCLUDES "${Flite_INCLUDE_DIR}") 35 | set(CMAKE_REQUIRED_LIBRARIES "${Flite_LIBRARY}") 36 | 37 | if(ALSA_FOUND) 38 | list(APPEND CMAKE_REQUIRED_LIBRARIES "${ALSA_LIBRARIES}") 39 | endif() 40 | 41 | check_cxx_source_compiles(" 42 | #include 43 | 44 | static int fliteAudioCb(const cst_wave *w, int start, int size, 45 | int last, cst_audio_streaming_info *asi) 46 | { 47 | (void)w; 48 | (void)start; 49 | (void)size; 50 | (void)last; 51 | (void)asi; 52 | return CST_AUDIO_STREAM_STOP; 53 | } 54 | 55 | int main() 56 | { 57 | cst_audio_streaming_info *asi = new_audio_streaming_info(); 58 | asi->asc = fliteAudioCb; // This fails for old Flite 59 | new_audio_streaming_info(); 60 | return 0; 61 | } 62 | " HAVE_FLITE) 63 | 64 | cmake_pop_check_state() 65 | 66 | include(FindPackageHandleStandardArgs) 67 | find_package_handle_standard_args(Flite 68 | FOUND_VAR 69 | Flite_FOUND 70 | REQUIRED_VARS 71 | Flite_LIBRARY 72 | Flite_INCLUDE_DIR 73 | HAVE_FLITE 74 | ) 75 | 76 | if(Flite_FOUND) 77 | add_library(Flite::Flite UNKNOWN IMPORTED) 78 | set_target_properties(Flite::Flite PROPERTIES 79 | IMPORTED_LOCATION "${Flite_LIBRARY}" 80 | INTERFACE_INCLUDE_DIRECTORIES "${Flite_INCLUDE_DIR}" 81 | ) 82 | if(ALSA_FOUND) 83 | set_target_properties(Flite::Flite PROPERTIES 84 | INTERFACE_LINK_LIBRARIES "${ALSA_LIBRARIES}" 85 | ) 86 | endif() 87 | endif() 88 | 89 | mark_as_advanced(Flite_LIBRARY Flite_INCLUDE_DIR HAVE_FLITE) 90 | 91 | 92 | if(HAVE_FLITE) 93 | set(Flite_FOUND 1) 94 | else() 95 | message("Flite was found, but the version is too old (<2.0.0)") 96 | set(Flite_FOUND 0) 97 | endif() 98 | -------------------------------------------------------------------------------- /src/plugins/tts/darwin/qtexttospeech_darwin.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHENGINE_DARWIN_H 6 | #define QTEXTTOSPEECHENGINE_DARWIN_H 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | Q_FORWARD_DECLARE_OBJC_CLASS(AVSpeechSynthesizer); 13 | Q_FORWARD_DECLARE_OBJC_CLASS(AVSpeechSynthesisVoice); 14 | Q_FORWARD_DECLARE_OBJC_CLASS(AVSpeechUtterance); 15 | 16 | QT_BEGIN_NAMESPACE 17 | 18 | class QTextToSpeechEngineDarwin : public QTextToSpeechEngine 19 | { 20 | Q_OBJECT 21 | 22 | public: 23 | QTextToSpeechEngineDarwin(const QVariantMap ¶meters, QObject *parent); 24 | ~QTextToSpeechEngineDarwin(); 25 | 26 | QList availableLocales() const override; 27 | QList availableVoices() const override; 28 | void say(const QString &text) override; 29 | void synthesize(const QString &text) override; 30 | void stop(QTextToSpeech::BoundaryHint boundaryHint) override; 31 | void pause(QTextToSpeech::BoundaryHint boundaryHint) override; 32 | void resume() override; 33 | double rate() const override; 34 | bool setRate(double rate) override; 35 | double pitch() const override; 36 | bool setPitch(double pitch) override; 37 | QLocale locale() const override; 38 | bool setLocale(const QLocale &locale) override; 39 | double volume() const override; 40 | bool setVolume(double volume) override; 41 | QVoice voice() const override; 42 | bool setVoice(const QVoice &voice) override; 43 | QTextToSpeech::State state() const override; 44 | QTextToSpeech::ErrorReason errorReason() const override; 45 | QString errorString() const override; 46 | 47 | void setState(QTextToSpeech::State state); 48 | 49 | bool ignoreNextUtterance = false; 50 | private: 51 | AVSpeechSynthesisVoice *fromQVoice(const QVoice &voice) const; 52 | QVoice toQVoice(AVSpeechSynthesisVoice *avVoice) const; 53 | void setError(QTextToSpeech::ErrorReason reason, const QString &string); 54 | AVSpeechUtterance *prepareUtterance(const QString &text); 55 | 56 | AVSpeechSynthesizer *m_speechSynthesizer; 57 | QVoice m_voice; 58 | QTextToSpeech::State m_state = QTextToSpeech::Error; 59 | QTextToSpeech::ErrorReason m_errorReason = QTextToSpeech::ErrorReason::Initialization; 60 | QString m_errorString; 61 | QAudioFormat m_format; 62 | 63 | double m_pitch = 0.0; 64 | double m_actualPitch = 1.0; 65 | double m_rate = 0.0; 66 | double m_volume = 1.0; 67 | }; 68 | 69 | QT_END_NAMESPACE 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/plugins/tts/flite/qtexttospeech_flite.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHENGINE_FLITE_H 6 | #define QTEXTTOSPEECHENGINE_FLITE_H 7 | 8 | #include "qtexttospeech_flite_processor.h" 9 | #include "qtexttospeechengine.h" 10 | #include "qvoice.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | QT_BEGIN_NAMESPACE 18 | 19 | class QTextToSpeechEngineFlite : public QTextToSpeechEngine 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | QTextToSpeechEngineFlite(const QVariantMap ¶meters, QObject *parent); 25 | ~QTextToSpeechEngineFlite() override; 26 | 27 | // Plug-in API: 28 | QList availableLocales() const override; 29 | QList availableVoices() const override; 30 | void say(const QString &text) override; 31 | void synthesize(const QString &text) override; 32 | void stop(QTextToSpeech::BoundaryHint boundaryHint) override; 33 | void pause(QTextToSpeech::BoundaryHint boundaryHint) override; 34 | void resume() override; 35 | double rate() const override; 36 | bool setRate(double rate) override; 37 | double pitch() const override; 38 | bool setPitch(double pitch) override; 39 | QLocale locale() const override; 40 | bool setLocale(const QLocale &locale) override; 41 | double volume() const override; 42 | bool setVolume(double volume) override; 43 | QVoice voice() const override; 44 | bool setVoice(const QVoice &voice) override; 45 | QTextToSpeech::State state() const override; 46 | QTextToSpeech::ErrorReason errorReason() const override; 47 | QString errorString() const override; 48 | 49 | Q_SIGNALS: 50 | void speaking(); 51 | void engineErrorOccurred(QTextToSpeech::ErrorReason, const QString &errorString); 52 | 53 | private slots: 54 | void changeState(QTextToSpeech::State newState); 55 | void setError(QTextToSpeech::ErrorReason error, const QString &errorString); 56 | 57 | private: 58 | QTextToSpeech::State m_state = QTextToSpeech::Error; 59 | QTextToSpeech::ErrorReason m_errorReason = QTextToSpeech::ErrorReason::Initialization; 60 | QString m_errorString; 61 | 62 | QVoice m_voice; 63 | double m_rate = 0; 64 | double m_pitch = 1; 65 | double m_volume = 1; 66 | 67 | // Voices mapped by their locale name. 68 | QMultiHash m_voices; 69 | 70 | // Thread for blocking operations 71 | QThread m_thread; 72 | std::unique_ptr m_processor; 73 | }; 74 | 75 | QT_END_NAMESPACE 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /src/tts/doc/src/qttexttospeech-index.qdoc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only 3 | 4 | /*! 5 | \page qttexttospeech-index.html 6 | \title Qt TextToSpeech 7 | \brief The Qt TextToSpeech module enables access to text-to-speech engines 8 | 9 | The Qt \TextToSpeech module enables a Qt application to read out text by 10 | using speech synthesis. This is especially useful in scenarios where the 11 | end-user cannot access the application's visual interface, for example, when 12 | driving or operating machinery. In such setups, the module can be used to 13 | read out incoming notifications or to provide turn-by-turn navigation 14 | instructions. 15 | 16 | The module does not provide a text-to-speech engine itself. Instead, it 17 | uses engines native to the operating system. See \l{Qt TextToSpeech Engines} 18 | for more details about this. 19 | 20 | \section1 Using the Module 21 | 22 | \section2 QML API 23 | 24 | \include {module-use.qdocinc} {using the qml api} {QtTextToSpeech} 25 | 26 | \section2 C++ API 27 | 28 | \include {module-use.qdocinc} {using the c++ api} 29 | 30 | \section3 Building with CMake 31 | 32 | \include {module-use.qdocinc} {building with cmake} {TextToSpeech} 33 | 34 | \section3 Building with qmake 35 | 36 | \include {module-use.qdocinc} {building_with_qmake} {texttospeech} 37 | 38 | \section1 Overviews and Important Topics 39 | 40 | \list 41 | \li \l{Changes to Qt TextToSpeech}{Changes in Qt 6} 42 | \endlist 43 | 44 | \section1 QML Types 45 | 46 | The following lists some important QML types. 47 | 48 | \generatelist qmltypesbymodule QtTextToSpeech 49 | 50 | \section1 C++ Classes 51 | 52 | The following lists some important C++ Classes. 53 | 54 | \generatelist classesbymodule QtTextToSpeech 55 | 56 | \section1 Reference and Examples 57 | 58 | \list 59 | \li \l{Qt TextToSpeech QML Types}{QML Types} 60 | \li \l{Qt TextToSpeech C++ Classes}{C++ Classes} 61 | \li \l{Qt TextToSpeech Examples}{Examples} 62 | \li \l{Qt TextToSpeech Engines}{Engine Documentation} 63 | \endlist 64 | 65 | \section1 Licenses and Attributions 66 | 67 | Qt TextToSpeech is available under commercial licenses from \l{The Qt Company}. 68 | In addition, it is available under free software licenses: 69 | The \l{GNU Lesser General Public License, version 3}, or 70 | the \l{GNU General Public License, version 2}. 71 | See \l{Qt Licensing} for further details. 72 | 73 | \omit 74 | Furthermore, Qt TextToSpeech in Qt \QtVersion may contain third party 75 | modules under the following permissive licenses: 76 | 77 | \annotatedlist attributions-qtspeech 78 | \endomit 79 | */ 80 | -------------------------------------------------------------------------------- /src/tts/qtexttospeechengine.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHENGINE_H 6 | #define QTEXTTOSPEECHENGINE_H 7 | 8 | // 9 | // W A R N I N G 10 | // ------------- 11 | // 12 | // This file is part of the Qt TextToSpeech plugin API, with limited compatibility 13 | // guarantees. 14 | // Usage of this API may make your code source and binary incompatible with 15 | // future versions of Qt. 16 | // 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | QT_BEGIN_NAMESPACE 26 | 27 | class QAudioFormat; 28 | 29 | class Q_TEXTTOSPEECH_EXPORT QTextToSpeechEngine : public QObject 30 | { 31 | Q_OBJECT 32 | 33 | public: 34 | explicit QTextToSpeechEngine(QObject *parent = nullptr); 35 | ~QTextToSpeechEngine(); 36 | 37 | virtual QTextToSpeech::Capabilities capabilities() const 38 | { 39 | return QTextToSpeech::Capability::None; 40 | } 41 | virtual QList availableLocales() const = 0; 42 | virtual QList availableVoices() const = 0; 43 | 44 | virtual void say(const QString &text) = 0; 45 | virtual void synthesize(const QString &text) = 0; 46 | virtual void stop(QTextToSpeech::BoundaryHint boundaryHint) = 0; 47 | virtual void pause(QTextToSpeech::BoundaryHint boundaryHint) = 0; 48 | virtual void resume() = 0; 49 | 50 | virtual double rate() const = 0; 51 | virtual bool setRate(double rate) = 0; 52 | virtual double pitch() const = 0; 53 | virtual bool setPitch(double pitch) = 0; 54 | virtual QLocale locale() const = 0; 55 | virtual bool setLocale(const QLocale &locale) = 0; 56 | virtual double volume() const = 0; 57 | virtual bool setVolume(double volume) = 0; 58 | virtual QVoice voice() const = 0; 59 | virtual bool setVoice(const QVoice &voice) = 0; 60 | virtual QTextToSpeech::State state() const = 0; 61 | virtual QTextToSpeech::ErrorReason errorReason() const = 0; 62 | virtual QString errorString() const = 0; 63 | 64 | protected: 65 | static QVoice createVoice(const QString &name, const QLocale &locale, QVoice::Gender gender, 66 | QVoice::Age age, const QVariant &data); 67 | static QVariant voiceData(const QVoice &voice); 68 | 69 | Q_SIGNALS: 70 | void stateChanged(QTextToSpeech::State state); 71 | void errorOccurred(QTextToSpeech::ErrorReason error, const QString &errorString); 72 | 73 | void sayingWord(const QString &word, qsizetype start, qsizetype length); 74 | void synthesized(const QAudioFormat &format, const QByteArray &data); 75 | }; 76 | 77 | QT_END_NAMESPACE 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /src/plugins/tts/android/src/qtexttospeech_android.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2021 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHENGINE_ANDROID_H 6 | #define QTEXTTOSPEECHENGINE_ANDROID_H 7 | 8 | #include "qtexttospeechengine.h" 9 | #include "qvoice.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | QT_BEGIN_NAMESPACE 18 | 19 | class QTextToSpeechEngineAndroid : public QTextToSpeechEngine 20 | { 21 | Q_OBJECT 22 | 23 | public: 24 | QTextToSpeechEngineAndroid(const QVariantMap ¶meters, QObject *parent); 25 | virtual ~QTextToSpeechEngineAndroid(); 26 | 27 | // Plug-in API: 28 | QTextToSpeech::Capabilities capabilities() const override; 29 | QList availableLocales() const override; 30 | QList availableVoices() const override; 31 | void say(const QString &text) override; 32 | void synthesize(const QString &text) override; 33 | void stop(QTextToSpeech::BoundaryHint boundaryHint) override; 34 | void pause(QTextToSpeech::BoundaryHint boundaryHint) override; 35 | void resume() override; 36 | double rate() const override; 37 | bool setRate(double rate) override; 38 | double pitch() const override; 39 | bool setPitch(double pitch) override; 40 | QLocale locale() const override; 41 | bool setLocale(const QLocale &locale) override; 42 | double volume() const override; 43 | bool setVolume(double volume) override; 44 | QVoice voice() const override; 45 | bool setVoice(const QVoice &voice) override; 46 | QTextToSpeech::State state() const override; 47 | QTextToSpeech::ErrorReason errorReason() const override; 48 | QString errorString() const override; 49 | 50 | public Q_SLOTS: 51 | void processNotifyReady(); 52 | void processNotifyError(int reason); 53 | void processNotifySpeaking(); 54 | void processNotifyRangeStart(int start, int end, int frame); 55 | void processNotifyBeginSynthesis(const QAudioFormat &format); 56 | void processNotifyAudioAvailable(const QByteArray &bytes); 57 | 58 | private: 59 | void setState(QTextToSpeech::State state); 60 | void setError(QTextToSpeech::ErrorReason reason, const QString &string); 61 | QVoice javaVoiceObjectToQVoice(QJniObject &obj) const; 62 | 63 | QJniObject m_speech; 64 | QTextToSpeech::State m_state = QTextToSpeech::Error; 65 | QTextToSpeech::ErrorReason m_errorReason = QTextToSpeech::ErrorReason::Initialization; 66 | QString m_errorString; 67 | QString m_text; 68 | QAudioFormat m_format; 69 | }; 70 | 71 | Q_DECLARE_JNI_CLASS(QtTextToSpeech, "org/qtproject/qt/android/speech/QtTextToSpeech") 72 | 73 | QT_END_NAMESPACE 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/tts/doc/src/qt6-changes.qdoc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only 3 | 4 | /*! 5 | \page qttexttospeech-changes-qt6.html 6 | \title Changes to Qt TextToSpeech 7 | \ingroup changes-qt-5-to-6 8 | \brief Migrate Qt TextToSpeech to Qt 6. 9 | 10 | Qt 6 is a result of the conscious effort to make the framework more 11 | efficient and easy to use. 12 | 13 | We try to maintain binary and source compatibility for all the public 14 | APIs in each release. But some changes were inevitable in an effort to 15 | make Qt a better framework. 16 | 17 | In this topic we summarize those changes in \l{Qt TextToSpeech}, and provide 18 | guidance to handle them. 19 | 20 | \section1 Available Engines 21 | 22 | All engines that were available in Qt 5 are also available in Qt 6.4. For a 23 | complete list of available engines in Qt 6.4, see \l{Qt TextToSpeech Engines}. 24 | 25 | Engines can now receive additional configuration parameters. When constructing 26 | a QTextToSpeech instance, pass a QVariantMap with engine-specific key/value 27 | pairs. 28 | 29 | \section1 API changes 30 | 31 | The \l{Qt TextToSpeech} module has undergone some basic consolidation and 32 | cleanup. There should be minimal porting effort to be able to switch to Qt 6. 33 | 34 | \section2 The QTextToSpeech class 35 | 36 | The \l QTextToSpeech::State enum value \c BackendError has been renamed to 37 | \c Error. Detailed error information is available via QTextToSpeech::errorReason() 38 | and QTextToSpeech::errorString(). 39 | 40 | The new \l{QTextToSpeech::}{engine} property allows changing of the engine on an 41 | initialized QTextToSpeech object. 42 | 43 | The \l{QTextToSpeech::}{pause} and \l{QTextToSpeech::stop} slots take a 44 | \l{QTextToSpeech::BoundaryHint} enum value. This will break the compilation for 45 | signal/slot connections that use PMF syntax if the signal has parameters that were 46 | previously ignored: 47 | 48 | \badcode 49 | connect(stopButton, &QPushButton, tts, &QTextToSpeech::stop); 50 | \endcode 51 | 52 | Either connect to a signal without parameters, or use a lambda and call the 53 | respective slot method explicitly: 54 | 55 | \code 56 | connect(stopButton, &QPushButton, tts, [tts]{ tts->stop(); }); 57 | \endcode 58 | 59 | \section2 The QVoice class 60 | 61 | Existing code using the QVoice class continues to work as before. QVoice objects 62 | can now be serialized via QDataStream. 63 | 64 | \section2 The QTextToSpeechEngine and QTextToSpeechPlugin classes 65 | 66 | These classes have been removed from the public API. They still exist and are 67 | used by the available engine implementations, but they are not part of the 68 | documented and supported API, and are likely to change in future releases. 69 | */ 70 | -------------------------------------------------------------------------------- /src/plugins/tts/flite/qtexttospeech_flite_processor.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHPROCESSOR_FLITE_H 6 | #define QTEXTTOSPEECHPROCESSOR_FLITE_H 7 | 8 | #include "qtexttospeechengine.h" 9 | #include "qvoice.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | #include 27 | 28 | QT_BEGIN_NAMESPACE 29 | 30 | class QFliteSynthesisProcess; 31 | 32 | class QTextToSpeechProcessorFlite : public QObject 33 | { 34 | Q_OBJECT 35 | 36 | public: 37 | QTextToSpeechProcessorFlite(QAudioDevice audioDevice); 38 | ~QTextToSpeechProcessorFlite(); 39 | 40 | struct VoiceInfo 41 | { 42 | int id; 43 | cst_voice *vox; 44 | void (*unregister_func)(cst_voice *vox); 45 | QString name; 46 | QString locale; 47 | QVoice::Gender gender; 48 | QVoice::Age age; 49 | }; 50 | 51 | Q_INVOKABLE void say(const QString &text, int voiceId, double pitch, double rate, double volume); 52 | Q_INVOKABLE void synthesize(const QString &text, int voiceId, double pitch, double rate, double volume); 53 | Q_INVOKABLE void pause(QTextToSpeech::BoundaryHint boundaryHint); 54 | Q_INVOKABLE void resume(); 55 | Q_INVOKABLE void stop(QTextToSpeech::BoundaryHint boundaryHint); 56 | 57 | const QList &voices() const; 58 | 59 | private: 60 | bool init(); 61 | bool checkVoice(int voiceId); 62 | 63 | void setError(QTextToSpeech::ErrorReason err, const QString &errorString = QString()); 64 | void updateState(QTextToSpeech::State); 65 | 66 | Q_SIGNALS: 67 | void errorOccurred(QTextToSpeech::ErrorReason error, const QString &errorString); 68 | void stateChanged(QTextToSpeech::State); 69 | void sayingWord(const QString &word, qsizetype begin, qsizetype length); 70 | void synthesized(const QAudioFormat &format, const QByteArray &array); 71 | 72 | private: 73 | QTextToSpeech::State m_state = {}; 74 | 75 | std::unique_ptr m_audioSink; 76 | const QAudioDevice m_audioDevice; 77 | float m_volume = 1.f; 78 | std::optional m_synthesisFormat; 79 | 80 | QList m_voices; 81 | 82 | // synthesis process 83 | friend class QFliteSynthesisProcess; 84 | std::unique_ptr m_synthesisProcess; 85 | 86 | void prepareAudioSink(QAudioFormat); 87 | }; 88 | 89 | QT_END_NAMESPACE 90 | 91 | #endif 92 | -------------------------------------------------------------------------------- /src/plugins/tts/sapi/qtexttospeech_sapi.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2015 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHENGINE_SAPI_H 6 | #define QTEXTTOSPEECHENGINE_SAPI_H 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | QT_BEGIN_NAMESPACE 20 | 21 | class QTextToSpeechEngineSapi : public QTextToSpeechEngine, public ISpNotifyCallback 22 | { 23 | Q_OBJECT 24 | 25 | public: 26 | QTextToSpeechEngineSapi(const QVariantMap ¶meters, QObject *parent); 27 | ~QTextToSpeechEngineSapi(); 28 | 29 | // Plug-in API: 30 | QList availableLocales() const override; 31 | QList availableVoices() const override; 32 | void say(const QString &text) override; 33 | void synthesize(const QString &text) override; 34 | void stop(QTextToSpeech::BoundaryHint boundaryHint) override; 35 | void pause(QTextToSpeech::BoundaryHint boundaryHint) override; 36 | void resume() override; 37 | double rate() const override; 38 | bool setRate(double rate) override; 39 | double pitch() const override; 40 | bool setPitch(double pitch) override; 41 | QLocale locale() const override; 42 | bool setLocale(const QLocale &locale) override; 43 | double volume() const override; 44 | bool setVolume(double volume) override; 45 | QVoice voice() const override; 46 | bool setVoice(const QVoice &voice) override; 47 | QTextToSpeech::State state() const override; 48 | QTextToSpeech::ErrorReason errorReason() const override; 49 | QString errorString() const override; 50 | 51 | HRESULT STDMETHODCALLTYPE NotifyCallback(WPARAM /*wParam*/, LPARAM /*lParam*/) override; 52 | friend class OputStream; 53 | 54 | private: 55 | bool isSpeaking() const; 56 | QMap voiceAttributes(ISpObjectToken *speechToken) const; 57 | QString voiceId(ISpObjectToken *speechToken) const; 58 | QLocale lcidToLocale(const QString &lcid) const; 59 | QVoice::Age toVoiceAge(const QString &age) const; 60 | void updateVoices(); 61 | void setError(QTextToSpeech::ErrorReason reason, const QString &string); 62 | 63 | QTextToSpeech::State m_state = QTextToSpeech::Error; 64 | QTextToSpeech::ErrorReason m_errorReason = QTextToSpeech::ErrorReason::Initialization; 65 | QString m_errorString; 66 | QVoice m_currentVoice; 67 | // Voices mapped by their locale name. 68 | QMultiHash m_voices; 69 | 70 | QString currentText; 71 | qsizetype textOffset = 0; 72 | ISpVoice *m_voice = nullptr; 73 | double m_pitch = 0.0; 74 | bool m_pauseRequested = false; 75 | }; 76 | QT_END_NAMESPACE 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/tts/doc/qttexttospeech.qdocconf: -------------------------------------------------------------------------------- 1 | include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) 2 | include($QT_INSTALL_DOCS/config/exampleurl-qtspeech.qdocconf) 3 | 4 | project = QtTextToSpeech 5 | description = Qt TextToSpeech Documentation 6 | version = $QT_VERSION 7 | 8 | sourcedirs += ../.. 9 | headerdirs += ../.. 10 | 11 | imagedirs += src/images 12 | 13 | exampledirs += ../../../examples/speech 14 | 15 | moduleheader = QtTextToSpeechDoc 16 | includepaths += . 17 | 18 | depends += qtcore qtdoc qtgui qtwidgets qtquick qtquickcontrols qtmultimedia qtcmake 19 | 20 | # Ignore \since commands for versions earlier than 6.4 21 | ignoresince = 6.4 22 | examplesinstallpath = speech 23 | 24 | # Path to the root of qtspeech (for automatic linking to source code) 25 | url.sources.rootdir = ../../.. 26 | 27 | # Defines the name of the project. You cannot use operators (+, =, -) in 28 | # the name. Properties for this project are set using a qhp..property 29 | # format. 30 | qhp.projects = QtTextToSpeech 31 | 32 | qhp.QtTextToSpeech.file = qttexttospeech.qhp 33 | qhp.QtTextToSpeech.namespace = org.qt-project.qttexttospeech.$QT_VERSION_TAG 34 | qhp.QtTextToSpeech.virtualFolder = qttexttospeech 35 | qhp.QtTextToSpeech.indexTitle = Qt TextToSpeech 36 | qhp.QtTextToSpeech.indexRoot = 37 | 38 | qhp.QtTextToSpeech.subprojects = manual examples classes qmltypes 39 | 40 | qhp.QtTextToSpeech.subprojects.classes.title = C++ Classes 41 | qhp.QtTextToSpeech.subprojects.classes.indexTitle = Qt TextToSpeech C++ Classes 42 | qhp.QtTextToSpeech.subprojects.classes.selectors = class 43 | qhp.QtTextToSpeech.subprojects.classes.sortPages = true 44 | 45 | qhp.QtTextToSpeech.subprojects.qmltypes.title = QML Types 46 | qhp.QtTextToSpeech.subprojects.qmltypes.indexTitle = Qt TextToSpeech QML Types 47 | qhp.QtTextToSpeech.subprojects.qmltypes.selectors = qmlclass 48 | qhp.QtTextToSpeech.subprojects.qmltypes.sortPages = true 49 | 50 | qhp.QtTextToSpeech.subprojects.examples.title = Examples 51 | qhp.QtTextToSpeech.subprojects.examples.indexTitle = Qt TextToSpeech Examples 52 | qhp.QtTextToSpeech.subprojects.examples.selectors = example 53 | qhp.QtTextToSpeech.subprojects.examples.sortPages = true 54 | 55 | qhp.QtTextToSpeech.subprojects.manual.title = Qt TextToSpeech 56 | qhp.QtTextToSpeech.subprojects.manual.indexTitle = Qt TextToSpeech module topics 57 | qhp.QtTextToSpeech.subprojects.manual.type = manual 58 | 59 | navigation.landingpage = "Qt TextToSpeech" 60 | navigation.cppclassespage = "Qt TextToSpeech C++ Classes" 61 | navigation.qmltypespage = "Qt TextToSpeech QML Types" 62 | # Auto-generate navigation linking based on "Qt TextToSpeech module topics": 63 | navigation.toctitles = "Qt TextToSpeech module topics" 64 | navigation.toctitles.inclusive = false 65 | 66 | # Highlighted examples in Data Processing & IO category 67 | manifestmeta.highlighted.names = "QtTextToSpeech/Quick Speech Example" 68 | 69 | # Allow no documentation warnings 70 | warninglimit = 0 71 | -------------------------------------------------------------------------------- /src/tts/qvoice.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QVOICE_H 6 | #define QVOICE_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | QT_BEGIN_NAMESPACE 15 | 16 | class QVoicePrivate; 17 | 18 | QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QVoicePrivate, Q_TEXTTOSPEECH_EXPORT) 19 | 20 | class Q_TEXTTOSPEECH_EXPORT QVoice 21 | { 22 | Q_GADGET 23 | Q_PROPERTY(QString name READ name CONSTANT) 24 | Q_PROPERTY(Gender gender READ gender CONSTANT) 25 | Q_PROPERTY(Age age READ age CONSTANT) 26 | Q_PROPERTY(QLocale locale READ locale CONSTANT) 27 | Q_PROPERTY(QLocale::Language language READ language STORED false REVISION(6, 6)) 28 | 29 | public: 30 | enum Gender { 31 | Male, 32 | Female, 33 | Unknown 34 | }; 35 | Q_ENUM(Gender) 36 | 37 | enum Age { 38 | Child, 39 | Teenager, 40 | Adult, 41 | Senior, 42 | Other 43 | }; 44 | Q_ENUM(Age) 45 | 46 | QVoice(); 47 | ~QVoice(); 48 | QVoice(const QVoice &other) noexcept; 49 | QVoice &operator=(const QVoice &other) noexcept; 50 | QVoice(QVoice &&other) noexcept = default; 51 | QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QVoice) 52 | 53 | void swap(QVoice &other) noexcept 54 | { d.swap(other.d); } 55 | 56 | friend inline bool operator==(const QVoice &lhs, const QVoice &rhs) noexcept 57 | { return lhs.isEqual(rhs); } 58 | friend inline bool operator!=(const QVoice &lhs, const QVoice &rhs) noexcept 59 | { return !lhs.isEqual(rhs); } 60 | 61 | #ifndef QT_NO_DATASTREAM 62 | friend inline QDataStream &operator<<(QDataStream &str, const QVoice &voice) 63 | { return voice.writeTo(str); } 64 | friend inline QDataStream &operator>>(QDataStream &str, QVoice &voice) 65 | { return voice.readFrom(str); } 66 | #endif 67 | 68 | QString name() const; 69 | QLocale locale() const; 70 | Gender gender() const; 71 | Age age() const; 72 | 73 | QLocale::Language language() const { return locale().language(); } 74 | 75 | static QString genderName(QVoice::Gender gender); 76 | static QString ageName(QVoice::Age age); 77 | 78 | private: 79 | QVoice(const QString &name, const QLocale &loc, Gender gender, Age age, const QVariant &data); 80 | bool isEqual(const QVoice &other) const noexcept; 81 | #ifndef QT_NO_DATASTREAM 82 | QDataStream &writeTo(QDataStream &) const; 83 | QDataStream &readFrom(QDataStream &); 84 | #endif 85 | 86 | QVariant data() const; 87 | 88 | QExplicitlySharedDataPointer d; 89 | friend class QVoicePrivate; 90 | friend class QTextToSpeechEngine; 91 | friend Q_TEXTTOSPEECH_EXPORT QDebug operator<<(QDebug, const QVoice &); 92 | }; 93 | 94 | #ifndef QT_NO_DEBUG_STREAM 95 | Q_TEXTTOSPEECH_EXPORT QDebug operator<<(QDebug, const QVoice &); 96 | #endif 97 | 98 | Q_DECLARE_SHARED(QVoice) 99 | 100 | QT_END_NAMESPACE 101 | 102 | Q_DECLARE_METATYPE(QVoice) 103 | Q_DECLARE_METATYPE(QVoice::Age) 104 | Q_DECLARE_METATYPE(QVoice::Gender) 105 | 106 | #endif 107 | -------------------------------------------------------------------------------- /tests/auto/qvoice/tst_qvoice.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only 3 | 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | class tst_QVoice : public QObject 10 | { 11 | Q_OBJECT 12 | 13 | private slots: 14 | void initTestCase_data(); 15 | void init(); 16 | 17 | void basic(); 18 | void sameEngine(); 19 | void datastream(); 20 | }; 21 | 22 | void tst_QVoice::initTestCase_data() 23 | { 24 | qInfo("Available text-to-speech engines:"); 25 | QTest::addColumn("engine"); 26 | const auto engines = QTextToSpeech::availableEngines(); 27 | if (!engines.size()) 28 | QSKIP("No speech engines available, skipping test case"); 29 | for (const auto &engine : engines) { 30 | QTest::addRow("%s", engine.toUtf8().constData()) << engine; 31 | qInfo().noquote() << "- " << engine; 32 | } 33 | } 34 | 35 | void tst_QVoice::init() 36 | { 37 | QFETCH_GLOBAL(QString, engine); 38 | if (engine == "speechd") { 39 | QTextToSpeech tts(engine); 40 | if (tts.state() == QTextToSpeech::Error) { 41 | QSKIP("speechd engine reported an error, " 42 | "make sure the speech-dispatcher service is running!"); 43 | } 44 | } else if (engine == "darwin" 45 | && QOperatingSystemVersion::current() <= QOperatingSystemVersion::MacOSMojave) { 46 | QTextToSpeech tts(engine); 47 | if (!tts.availableLocales().size()) 48 | QSKIP("iOS engine is not functional on macOS <= 10.14"); 49 | } 50 | } 51 | 52 | /* 53 | Test basic value type semantics. 54 | */ 55 | void tst_QVoice::basic() 56 | { 57 | QFETCH_GLOBAL(QString, engine); 58 | QTextToSpeech tts(engine); 59 | QTRY_COMPARE(tts.state(), QTextToSpeech::Ready); 60 | const QList voices = tts.availableVoices(); 61 | QVERIFY(voices.size()); 62 | 63 | QVoice emptyVoice; 64 | for (const auto &voice : voices) { 65 | QCOMPARE(voice, voice); 66 | QCOMPARE(voice.locale(), tts.locale()); 67 | QVERIFY(voice != emptyVoice); 68 | 69 | QVoice voiceCopy = voice; 70 | QCOMPARE(voiceCopy, voice); 71 | } 72 | 73 | QVoice movedFrom = voices.first(); 74 | QVoice movedTo = std::move(movedFrom); 75 | QCOMPARE(movedTo, voices.first()); 76 | QCOMPARE(movedFrom, emptyVoice); 77 | } 78 | 79 | /* 80 | A QVoice from one engine should match the same voice from the same engine. 81 | */ 82 | void tst_QVoice::sameEngine() 83 | { 84 | QFETCH_GLOBAL(QString, engine); 85 | QTextToSpeech tts1(engine); 86 | QTextToSpeech tts2(engine); 87 | QTRY_COMPARE(tts1.state(), QTextToSpeech::Ready); 88 | QTRY_COMPARE(tts2.state(), QTextToSpeech::Ready); 89 | 90 | const QList voices = tts1.availableVoices(); 91 | QVERIFY(voices.size()); 92 | QCOMPARE(tts1.availableVoices(), tts2.availableVoices()); 93 | 94 | for (const auto &voice : voices) 95 | QVERIFY(tts2.availableVoices().indexOf(voice) != -1); 96 | } 97 | 98 | void tst_QVoice::datastream() 99 | { 100 | QFETCH_GLOBAL(QString, engine); 101 | QVoice savedVoice; 102 | 103 | QByteArray storage; 104 | { 105 | QTextToSpeech tts(engine); 106 | QTRY_COMPARE(tts.state(), QTextToSpeech::Ready); 107 | const QList voices = tts.availableVoices(); 108 | QVERIFY(voices.size()); 109 | savedVoice = voices.first(); 110 | 111 | QDataStream writeStream(&storage, QIODevice::WriteOnly); 112 | writeStream << savedVoice; 113 | QVERIFY(storage.size() > 0); 114 | } 115 | 116 | QVoice loadedVoice; 117 | QDataStream readStream(storage); 118 | readStream >> loadedVoice; 119 | 120 | QCOMPARE(loadedVoice, savedVoice); 121 | } 122 | 123 | QTEST_MAIN(tst_QVoice) 124 | #include "tst_qvoice.moc" 125 | -------------------------------------------------------------------------------- /src/plugins/tts/winrt/qtexttospeech_winrt_audiosource.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #ifndef QTEXTTOSPEECHENGINE_WINRT_AUDIOSOURCE_H 6 | #define QTEXTTOSPEECHENGINE_WINRT_AUDIOSOURCE_H 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | using namespace ABI::Windows::Foundation; 22 | using namespace ABI::Windows::Media::SpeechSynthesis; 23 | using namespace ABI::Windows::Storage::Streams; 24 | using namespace Microsoft::WRL; 25 | 26 | QT_BEGIN_NAMESPACE 27 | 28 | using StreamReadyHandler = IAsyncOperationCompletedHandler; 29 | using BytesReadyHandler = IAsyncOperationWithProgressCompletedHandler; 30 | 31 | class AudioSource final : public QIODevice, public QComObject 32 | { 33 | Q_OBJECT 34 | public: 35 | AudioSource(ComPtr> synthOperation); 36 | 37 | bool isSequential() const override { return true; } 38 | 39 | void close() override; 40 | qint64 readData(char *data, qint64 maxlen) override; 41 | qint64 writeData(const char *data, qint64 len) override { return 0; } 42 | 43 | bool atEnd() const override; 44 | qint64 bytesAvailable() const override; 45 | 46 | QAudioFormat format() const { return audioFormat; } 47 | 48 | enum PauseState { 49 | NoPause, 50 | PauseRequested, 51 | Paused 52 | } m_pause = NoPause; 53 | 54 | void pause(quint64 atByte) 55 | { 56 | m_pause = PauseRequested; 57 | m_pauseRequestedAt = atByte; 58 | } 59 | 60 | void resume() 61 | { 62 | m_pause = NoPause; 63 | m_pauseRequestedAt = 0; 64 | if (bytesAvailable()) 65 | emit readyRead(); 66 | } 67 | 68 | struct Boundary { 69 | enum Type { Word, Sentence, Unknown } type; 70 | QString text; 71 | int beginIndex; 72 | int endIndex; 73 | qint64 startTime; 74 | friend inline bool operator<(const Boundary &lhs, const Boundary &rhs) 75 | { 76 | return lhs.startTime < rhs.startTime; 77 | } 78 | }; 79 | 80 | QList boundaryData() const 81 | { 82 | return boundaries; 83 | } 84 | 85 | // completion handler for synthesising the stream 86 | HRESULT STDMETHODCALLTYPE Invoke(IAsyncOperation *operation, 87 | AsyncStatus status) override; 88 | // completion handler for reading from the stream 89 | HRESULT STDMETHODCALLTYPE Invoke(IAsyncOperationWithProgress *read, 90 | AsyncStatus status) override; 91 | 92 | Q_SIGNALS: 93 | void streamReady(const QAudioFormat &format); 94 | void errorInStream(); 95 | 96 | private: 97 | // lifetime is controlled via IUnknown reference counting, make sure 98 | // we don't destroy by accident, polymorphically, or via a QObject parent 99 | ~AudioSource() override; 100 | 101 | qint64 bytesInBuffer() const; 102 | bool fetchMore(); 103 | 104 | QAudioFormat audioFormat; 105 | 106 | // The input stream that gives access to the synthesis stream. We keep the 107 | // async operation so that we can cancel it if we get destroyed prematurely. 108 | ComPtr> synthOperation; 109 | ComPtr inputStream; 110 | ComPtr randomAccessStream; 111 | // the current ReadAsync operation that yields an IBuffer 112 | ComPtr> readOperation; 113 | ComPtr m_buffer; 114 | // access to the raw pcm bytes in the IBuffer; this took much reading of Windows header files... 115 | ComPtr<::Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess; 116 | // The data in the IBuffer might be paritally consumed 117 | UINT32 m_bufferOffset = 0; 118 | // RIFF header has been checked at the beginning of the stream 119 | bool m_riffHeaderChecked = false; 120 | quint64 m_bytesRead = 0; 121 | quint64 m_pauseRequestedAt = 0; 122 | std::optional m_pauseDetectionSilenceCount; 123 | 124 | void populateBoundaries(); 125 | QList boundaries; 126 | }; 127 | 128 | QT_END_NAMESPACE 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /src/tts/qml/qdeclarativetexttospeech.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qdeclarativetexttospeech_p.h" 6 | #include "qvoiceselectorattached_p.h" 7 | 8 | #include 9 | 10 | QT_BEGIN_NAMESPACE 11 | 12 | using namespace Qt::StringLiterals; 13 | 14 | /*! 15 | \class QDeclarativeTextToSpeech 16 | \internal 17 | */ 18 | 19 | /*! 20 | \internal 21 | 22 | Constructor that delays the initialization of the text-to-speech 23 | engine until the QML engine sets the engine. 24 | */ 25 | QDeclarativeTextToSpeech::QDeclarativeTextToSpeech(QObject *parent) 26 | : QTextToSpeech(u"none"_s, parent) 27 | {} 28 | 29 | /*! 30 | Intercept the calls to QTextToSpeech::engine/setEngine so that we can 31 | delay the setting of the engine until the component is completely parsed. 32 | */ 33 | QString QDeclarativeTextToSpeech::engine() const 34 | { 35 | if (!m_engine.isEmpty()) 36 | return m_engine; 37 | return QTextToSpeech::engine(); 38 | } 39 | 40 | void QDeclarativeTextToSpeech::setEngine(const QString &engine) 41 | { 42 | if (m_engine == engine) 43 | return; 44 | 45 | m_engine = engine; 46 | if (m_complete) 47 | QTextToSpeech::setEngine(m_engine, m_engineParameters); 48 | emit engineChanged(m_engine); 49 | } 50 | 51 | /*! 52 | \qmlproperty map TextToSpeech::engineParameters 53 | \brief This property holds engine-specific parameters. 54 | 55 | \sa engine 56 | */ 57 | QVariantMap QDeclarativeTextToSpeech::engineParameters() const 58 | { 59 | return m_engineParameters; 60 | } 61 | 62 | void QDeclarativeTextToSpeech::setEngineParameters(const QVariantMap ¶meters) 63 | { 64 | if (m_engineParameters == parameters) 65 | return; 66 | 67 | m_engineParameters = parameters; 68 | // if changed after initialization, then we need to recreate the engine 69 | if (m_complete) 70 | QTextToSpeech::setEngine(QTextToSpeech::engine(), m_engineParameters); 71 | emit engineParametersChanged(); 72 | } 73 | 74 | void QDeclarativeTextToSpeech::classBegin() 75 | { 76 | } 77 | 78 | void QDeclarativeTextToSpeech::componentComplete() 79 | { 80 | m_complete = true; 81 | QTextToSpeech::setEngine(m_engine, m_engineParameters); 82 | selectVoice(); 83 | } 84 | 85 | void QDeclarativeTextToSpeech::selectVoice() 86 | { 87 | if (!m_complete || !m_voiceSelector) 88 | return; 89 | 90 | if (state() != QTextToSpeech::Ready) { 91 | // for asynchronously initialized engines we have to wait for it to be ready 92 | connect(this, &QTextToSpeech::stateChanged, this, &QDeclarativeTextToSpeech::selectVoice, 93 | Qt::SingleShotConnection); 94 | } else { 95 | auto voices = findVoices(m_voiceSelector->selectionCriteria()); 96 | if (!voices.isEmpty()) 97 | setVoice(voices.first()); 98 | } 99 | } 100 | 101 | 102 | QList QDeclarativeTextToSpeech::findVoices(const QVariantMap &criteria) const 103 | { 104 | const QLocale *plocale = nullptr; 105 | // if we limit by locale, then limit the search to the voices for that 106 | if (const auto &it = criteria.find(QLatin1String("locale")); it != criteria.end()) { 107 | if (it->metaType() == QMetaType::fromType()) 108 | plocale = static_cast(it->constData()); 109 | } 110 | QList voices = allVoices(plocale); 111 | 112 | voices.removeIf([&criteria](const QVoice &voice){ 113 | const QMetaObject &mo = QVoice::staticMetaObject; 114 | for (const auto &[key, value] : criteria.asKeyValueRange()) { 115 | const int propertyIndex = mo.indexOfProperty(key.toUtf8().constData()); 116 | if (propertyIndex < 0) { 117 | qWarning("QVoice doesn't have a property %s!", qPrintable(key)); 118 | } else { 119 | const QMetaProperty prop = mo.property(propertyIndex); 120 | const QVariant voiceValue = prop.readOnGadget(&voice); 121 | if (voiceValue.metaType() == QMetaType::fromType()) { 122 | if (voiceValue.value() != value.toLocale().language()) 123 | return true; 124 | } else if (value.metaType() == QMetaType::fromType()) { 125 | if (!value.value().match(voiceValue.toString()).hasMatch()) 126 | return true; 127 | } else if (voiceValue != value) { 128 | return true; 129 | } 130 | } 131 | } 132 | return false; 133 | }); 134 | 135 | return voices; 136 | } 137 | 138 | 139 | QT_END_NAMESPACE 140 | -------------------------------------------------------------------------------- /examples/speech/quickspeech/doc/src/quickspeech.qdoc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only 3 | 4 | /*! 5 | \example quickspeech 6 | \title Quick Speech Example 7 | \examplecategory {Data Processing & I/O} 8 | \ingroup qttexttospeech_examples 9 | \brief The Quick Speech example reads out user-provided text. 10 | \meta tags {quick Android} 11 | 12 | \image quickspeech-example.png {Screenshot showing a tool for text to speech 13 | with options to change engine, locale, voice, volume, pitch, and 14 | rate} 15 | 16 | The \e{Quick Speech} example demonstrates how the \l[QML]{TextToSpeech} type 17 | can be used in a \l{Qt Quick} application to read out text and to control 18 | the speech. 19 | 20 | The example uses \l{Qt Quick Controls} to provide controls for the speech's 21 | pitch, volume, and rate. It also lets the user select an engine, a 22 | language, and a voice. 23 | 24 | \section1 Initializing a TextToSpeech 25 | First, we initialize the text to speech object \c{tts}: 26 | 27 | \snippet quickspeech/Main.qml initialize 28 | 29 | \section1 Getting the status 30 | 31 | \image status.gif {Gif showing a status example of the tool} 32 | 33 | Switch cases are used to update the Label \c statusLabel in the footer. 34 | 35 | \snippet quickspeech/Main.qml stateChanged 36 | 37 | \section1 Highlighting words as they are spoken 38 | 39 | The TextArea \c input is used to get the text to input and the 40 | \l{TextToSpeech::sayingWord}{onSayingWord} signal as the trigger and also 41 | to know the position to highlight words as they are spoken. 42 | 43 | \snippet quickspeech/Main.qml sayingWord 44 | 45 | The TextArea \c input is declared here: 46 | 47 | \quotefromfile quickspeech/Main.qml 48 | \skipto ColumnLayout { 49 | \printuntil } 50 | 51 | \section1 Controlling speech 52 | 53 | \l Button types are arranged with a \l RowLayout and configured to control 54 | the TextToSpeech \c tts. 55 | 56 | \section2 The speak button 57 | 58 | A \l Button is created labeled "Speak". It is enabled if \c tts's state 59 | property is either \l{QTextToSpeech::}{Paused} or \l{QTextToSpeech::}{Ready}. 60 | When the button is clicked, the available voices on the target devices are 61 | retrieved, and \c tts.voice is set to the currently selected voice of 62 | \c voicesComboBox. Then TextToSpeech::say() is called and is passed the 63 | text in the \c inputbox. 64 | 65 | \snippet quickspeech/Main.qml say0 66 | 67 | \section1 The pause, resume, and stop buttons 68 | 69 | These buttons are similar in implementation to the \c Speak button: 70 | 71 | \snippet quickspeech/Main.qml pause 72 | \snippet quickspeech/Main.qml resume 73 | \snippet quickspeech/Main.qml stop 74 | 75 | \section1 Selecting text to speech options 76 | 77 | A \l GridLayout is used to arrange the controls and labels for the selection 78 | of engine, locale, voice, volume, pitch, and rate options for text to 79 | speech synthesis. 80 | 81 | \section2 Selecting engine, locale, and voice 82 | 83 | A group of \l{ComboBox} components are used for selecting these parameters. 84 | 85 | For the engine selection ComboBox, \c tts.availableEngines() is used as the 86 | model. 87 | 88 | The \l{ComboBox::activated}{onActivated} triggers assigning tts.engine the 89 | current text at the ComboBoxes current index. 90 | 91 | \skipto Label { 92 | \printuntil updateVoices() 93 | \printto Label { 94 | 95 | The last two lines in the above code snippet show that the available locales 96 | and voices are updated at this point as well, as they are dependent on the 97 | selected engine. Those functions are covered in a 98 | \l{Updating available options}{following section}. 99 | 100 | The \c localesComboBox is implemented the same way as \c engineComboBox, but 101 | without updating the available engines. 102 | 103 | 104 | \printuntil id: voicesComboBox 105 | \printto Label 106 | 107 | \section2 Selecting volume, pitch, and rate 108 | 109 | These controls are implemented with \l{Slider}{Sliders} as follows: 110 | 111 | \printto footer: Label { 112 | 113 | \section1 Updating available options 114 | 115 | By using the \c Component.onCompleted signal, the following is done 116 | once the root ApplicationWindow has been instantiated. 117 | 118 | \list 119 | \li The \c enginesComboBox index is set to the currently set engine of 120 | \c{tts}. 121 | \li The available locales and voices are updated. 122 | \li The current state of \c tts is signaled. 123 | \endlist 124 | 125 | \skipto Component.onCompleted: { 126 | \printto } 127 | 128 | Used throughout the application, the \c updateLocales() and \c updateVoice() 129 | functions are implemented as follows: 130 | 131 | \printuntil voicesComboBox.currentIndex = indexOfVoice 132 | 133 | \include examples-run.qdocinc 134 | 135 | */ 136 | -------------------------------------------------------------------------------- /licenseRule.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "comment": ["file_pattern_ending: strings matched against the end of a file name.", 4 | "location keys: regular expression matched against the beginning of", 5 | "the file path (relative to the git submodule root).", 6 | "spdx: list of SPDX-License-Expression's allowed in the matching files.", 7 | "-------------------------------------------------------", 8 | "Files with the following endings are Build System licensed,", 9 | "unless they are examples", 10 | "Files with other endings can also be build system files" 11 | ], 12 | "file_pattern_ending": ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf", 13 | "configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in", 14 | ".cmake.conf", ".tag", ".yaml", "ci_config_linux.json", 15 | "configure.json", "BLACKLIST"], 16 | "location": { 17 | "": { 18 | "comment": "Default", 19 | "file type": "build system", 20 | "spdx": ["BSD-3-Clause"] 21 | }, 22 | "(.*)(examples/|snippets/)": { 23 | "comment": "Example takes precedence", 24 | "file type": "examples and snippets", 25 | "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] 26 | } 27 | } 28 | }, 29 | { 30 | "comments": ["Files with the following endings are infrastructure licensed"], 31 | "file_pattern_ending": [".gitattributes", ".gitignore", ".gitmodules", ".gitreview", 32 | "clang-format", "licenseRule.json", "REUSE.toml"], 33 | "location":{ 34 | "": { 35 | "comment": "Default", 36 | "file type": "infrastructure", 37 | "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] 38 | } 39 | } 40 | }, 41 | { 42 | "comments": ["Files with the following endings are Tool licensed,", 43 | "unless they are examples.", 44 | "Files with other endings can also be tool files."], 45 | "file_pattern_ending": [".sh", ".py", ".pl", ".bat", ".ps1"], 46 | "location":{ 47 | "": { 48 | "comment": "Default", 49 | "file type": "tools and utils", 50 | "spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"] 51 | }, 52 | "(.*)(examples/|snippets/)": { 53 | "comment": "Example takes precedence", 54 | "file type": "examples and snippets", 55 | "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] 56 | } 57 | } 58 | }, 59 | { 60 | "comment": "Files with the following endings are Documentation licensed.", 61 | "file_pattern_ending": [".qdoc", ".qdocinc" , ".qdocconf", "README", "qt_attribution.json", 62 | "config_help.txt"], 63 | "location":{ 64 | "": { 65 | "comment": "", 66 | "file type": "documentation", 67 | "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] 68 | } 69 | } 70 | }, 71 | { 72 | "comment": ["All other files", 73 | "The licensing is defined only by the file location in the Qt module repository.", 74 | "NO key for this case!", 75 | "This needs to be the last entry of the file."], 76 | "location": { 77 | "": { 78 | "comment": "Default", 79 | "file type": "module and plugin", 80 | "spdx": ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] 81 | }, 82 | "dist/": { 83 | "comment": "Default", 84 | "file type": "documentation", 85 | "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] 86 | }, 87 | "src/": { 88 | "comment": "Default", 89 | "file type": "module and plugin", 90 | "spdx": ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] 91 | }, 92 | "tests/": { 93 | "comment": "Default", 94 | "file type": "test", 95 | "spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only"] 96 | }, 97 | "(.*)(examples/|snippets/)": { 98 | "comment": "Default", 99 | "file type": "examples and snippets", 100 | "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] 101 | }, 102 | "(.*|examples)(.*)/doc/images": { 103 | "comment": "Default", 104 | "file type": "documentation", 105 | "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] 106 | } 107 | } 108 | } 109 | ] 110 | -------------------------------------------------------------------------------- /src/tts/qtexttospeechengine.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qtexttospeechengine.h" 6 | 7 | #include 8 | 9 | QT_BEGIN_NAMESPACE 10 | 11 | 12 | /*! 13 | \class QTextToSpeechEngine 14 | \inmodule QtTextToSpeech 15 | \brief The QTextToSpeechEngine class is the base for text-to-speech engine integrations. 16 | \internal 17 | 18 | An engine implementation must derive from QTextToSpeechEngine and implement all 19 | its pure virtual methods. 20 | */ 21 | 22 | /*! 23 | \fn QTextToSpeech::Capabilities QTextToSpeechEngine::capabilities() const 24 | 25 | Implementation of \l QTextToSpeech::engineCapabilities(). If this function is 26 | not implemented, then the capabilities will be read from the plugin meta data. 27 | */ 28 | 29 | /*! 30 | \fn QList QTextToSpeechEngine::availableLocales() const 31 | 32 | Implementation of \l QTextToSpeech::availableLocales(). 33 | */ 34 | 35 | /*! 36 | \fn QList QTextToSpeechEngine::availableVoices() const 37 | 38 | Implementation of \l QTextToSpeech::availableVoices(). 39 | */ 40 | 41 | /*! 42 | \fn void QTextToSpeechEngine::say(const QString &text) 43 | 44 | Implementation of \l {QTextToSpeech::say()}{QTextToSpeech::say}(\a text). 45 | */ 46 | 47 | /*! 48 | \fn void QTextToSpeechEngine::stop(QTextToSpeech::BoundaryHint hint) 49 | 50 | Implementation of \l QTextToSpeech::stop(). 51 | */ 52 | 53 | /*! 54 | \fn void QTextToSpeechEngine::pause(QTextToSpeech::BoundaryHint hint) 55 | 56 | Implementation of \l QTextToSpeech::pause(). 57 | */ 58 | 59 | /*! 60 | \fn void QTextToSpeechEngine::resume() 61 | 62 | Implementation of \l QTextToSpeech::resume(). 63 | */ 64 | 65 | /*! 66 | \fn void QTextToSpeechEngine::rate() const 67 | 68 | Implementation of \l QTextToSpeech::rate(). 69 | */ 70 | 71 | /*! 72 | \fn bool QTextToSpeechEngine::setRate(double rate) 73 | 74 | Implementation of \l {QTextToSpeech::setRate()}{QTextToSpeech::setRate}(\a rate). 75 | 76 | Return \c true if the operation was successful. 77 | */ 78 | 79 | /*! 80 | \fn void QTextToSpeechEngine::pitch() const 81 | 82 | Implementation of \l QTextToSpeech::pitch(). 83 | */ 84 | 85 | /*! 86 | \fn bool QTextToSpeechEngine::setPitch(double pitch) 87 | 88 | Implementation of \l {QTextToSpeech::setPitch()}{QTextToSpeech::setPitch}(\a pitch). 89 | 90 | Return \c true if the operation was successful. 91 | */ 92 | 93 | /*! 94 | \fn QLocale QTextToSpeechEngine::locale() const 95 | 96 | Implementation of QTextToSpeech::locale(). 97 | */ 98 | 99 | /*! 100 | \fn bool QTextToSpeechEngine::setLocale(const QLocale &locale) 101 | 102 | Implementation \l {QTextToSpeech::setLocale()}{QTextToSpeech::setLocale}(\a locale). 103 | 104 | Return \c true if the operation was successful. In this case, the 105 | current voice (as returned by voice()) should also be updated to a 106 | new, valid value. 107 | */ 108 | 109 | /*! 110 | \fn double QTextToSpeechEngine::volume() const 111 | 112 | Implementation of QTextToSpeech::volume(). 113 | */ 114 | 115 | /*! 116 | \fn bool QTextToSpeechEngine::setVolume(double volume) 117 | 118 | Implementation of \l {QTextToSpeech::setVolume()}{QTextToSpeech::setVolume}(\a volume). 119 | 120 | Return \c true if the operation was successful. 121 | */ 122 | 123 | /*! 124 | \fn QVoice QTextToSpeechEngine::voice() const 125 | 126 | Implementation of \l QTextToSpeech::voice(). 127 | */ 128 | 129 | /*! 130 | \fn bool QTextToSpeechEngine::setVoice(const QVoice &voice) 131 | 132 | Implementation of \l {QTextToSpeech::setVoice()}{QTextToSpeech::setVoice}(\a voice). 133 | 134 | Return \c true if the operation was successful. 135 | */ 136 | 137 | /*! 138 | \fn QTextToSpeech::State QTextToSpeechEngine::state() const 139 | 140 | Implementation of QTextToSpeech::state(). 141 | */ 142 | 143 | /*! 144 | \fn void QTextToSpeechEngine::stateChanged(QTextToSpeech::State state) 145 | 146 | Emitted when the text-to-speech engine \a state has changed. 147 | 148 | This signal is connected to QTextToSpeech::stateChanged() signal. 149 | */ 150 | 151 | /*! 152 | Constructs the text-to-speech engine base class with \a parent. 153 | */ 154 | QTextToSpeechEngine::QTextToSpeechEngine(QObject *parent): 155 | QObject(parent) 156 | { 157 | } 158 | 159 | QTextToSpeechEngine::~QTextToSpeechEngine() 160 | { 161 | } 162 | 163 | /*! 164 | Creates a voice for a text-to-speech engine. 165 | 166 | Parameters \a name, \a locale, \a gender, \a age and \a data are directly 167 | stored in the QVoice instance. 168 | */ 169 | QVoice QTextToSpeechEngine::createVoice(const QString &name, const QLocale &locale, 170 | QVoice::Gender gender, QVoice::Age age, 171 | const QVariant &data) 172 | { 173 | return QVoice(name, locale, gender, age, data); 174 | } 175 | 176 | /*! 177 | Returns the engine-specific private data for the given \a voice. 178 | 179 | */ 180 | QVariant QTextToSpeechEngine::voiceData(const QVoice &voice) 181 | { 182 | return voice.data(); 183 | } 184 | 185 | QT_END_NAMESPACE 186 | -------------------------------------------------------------------------------- /src/tts/doc/src/qttexttospeech-engines.qdoc: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only 3 | 4 | /*! 5 | \page qttexttospeech-engines.html 6 | \title Qt TextToSpeech Engines 7 | \brief Engine specific documentation 8 | 9 | \l{Qt TextToSpeech} supports several engine implementations for different platforms, and 10 | with different tradeoffs between capabilities, availability, and runtime cost. 11 | 12 | An engine can be selected when a QTextToSpeech instance is constructed, or on an already 13 | instantiated object by setting the \l {QTextToSpeech::}{engine} property. If no engine 14 | is specified, the preferred engine for the current platform will be used. Call 15 | \l{QTextToSpeech::}{availableEngines()} to get the list of engines that can be used on 16 | the current system. This will include a "mock" engine that is used for testing, and that 17 | should not be deployed to target systems. 18 | 19 | When setting the engine, applications can pass a QVariantMap with key/value pairs of 20 | engine specific parameters through to the engine. The following sections list the 21 | configuration parameters supported for each engine. Parameters that are not supported 22 | by the engine will be silently ignored. 23 | 24 | \section1 WinRT 25 | 26 | The "winrt" engine uses the APIs from the \l{https://docs.microsoft.com/en-us/uwp/api/windows.media.speechsynthesis} 27 | {Windows.Media.SpeechSynthesis Namespace}. It requires a recent Windows SDK, and 28 | is not available when using the MinGW compiler. The engine provides access to all 29 | voices available for installation on current Windows versions. 30 | 31 | The implementation uses QAudioSink from \l{Qt Multimedia} to play the PCM data 32 | stream generated by the synthesizer to an audio device. 33 | 34 | \table 35 | \header 36 | \li Name 37 | \li Type 38 | \li Remarks 39 | \row 40 | \li audioDevice 41 | \li QAudioDevice 42 | \li 43 | \endtable 44 | 45 | \section1 SAPI 46 | 47 | The "sapi" engine uses the \l{https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms723627(v=vs.85)} 48 | {SAPI 5.3} framework that is included in the Windows SDK. It provides a limited selection 49 | of voices, with reduced quality compared to the "winrt" engine. 50 | 51 | The SAPI engine does not support any engine specific parameters. 52 | 53 | \section1 Darwin 54 | 55 | The "darwin" engine uses the \l{https://developer.apple.com/documentation/avfoundation/speech_synthesis?language=objc} 56 | {AVFoundation} framework that is available on iOS devices and on macOS 10.15. The 57 | documentation of the framework states support for macOS 10.14 as well, but by default 58 | no voices are available on that platform. 59 | 60 | The Darwin engine does not support any engine specific parameters. 61 | 62 | \section1 Android 63 | 64 | The "android" engine is the only engine available on the Android platform. It uses the 65 | \l{https://developer.android.com/reference/android/speech/tts/TextToSpeech}{TextToSpeech} 66 | package, which in turn supports multiple engine backends. 67 | 68 | \note The "android" engine does not have the \l{QTextToSpeech::Capabilities} 69 | {PauseResume} capability. 70 | 71 | \table 72 | \header 73 | \li Name 74 | \li Type 75 | \li Remarks 76 | \row 77 | \li androidEngine 78 | \li QString 79 | \li There is no API in Qt to get the list of installed engines. 80 | \endtable 81 | 82 | 83 | \section1 Flite 84 | 85 | The "flite" engine uses the \l{https://github.com/festvox/flite}{flite} synthesizer. 86 | The engine's small footprint makes it particularly useful for embedded environments. 87 | The plugin requires at least Flite 2.2, and uses \l QAudioSink from \l{Qt Multimedia} 88 | to render the generated PCM data stream. 89 | 90 | The engine plugin searches for voice libraries in the directories listed in the 91 | \c LD_LIBRARY_PATH environment variable, and falls back to search common library 92 | locations such as \c {/usr/lib}, \c {/usr/lib64}, and \c {/usr/lib/x86_64-linux-gnu}. 93 | 94 | If Flite is used as a static library, then the desired voice libraries also need to 95 | be statically linked into the engine plugin. There is currently not build system API 96 | implemented for selecting such voice libraries when configuring Qt. 97 | 98 | \table 99 | \header 100 | \li Name 101 | \li Type 102 | \li Remarks 103 | \row 104 | \li audioDevice 105 | \li QAudioDevice 106 | \li 107 | \endtable 108 | 109 | \section1 speech-dispatcher 110 | 111 | The "speechd" engine communicates with the 112 | \l{https://htmlpreview.github.io/?https://github.com/brailcom/speechd/blob/master/doc/speech-dispatcher.html#Top} 113 | {speech-dispatcher} daemon, and requires at least libspeechd 0.9. 114 | 115 | \note The speech-dispatcher engine does not have the \l {QTextToSpeech::Capabilities} 116 | {WordByWordProgress} or \l {QTextToSpeech::Capabilities}{Synthesize} capabilities. 117 | 118 | The speech-dispatcher engine does not support any engine specific parameters. 119 | */ 120 | -------------------------------------------------------------------------------- /src/tts/qml/qvoiceselectorattached.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qvoiceselectorattached_p.h" 6 | #include "qdeclarativetexttospeech_p.h" 7 | 8 | #include 9 | 10 | QT_BEGIN_NAMESPACE 11 | 12 | using namespace Qt::StringLiterals; 13 | 14 | /*! 15 | \qmltype VoiceSelector 16 | \inqmlmodule QtTextToSpeech 17 | \since 6.6 18 | \brief Provides attached properties for selecting the voice of a TextToSpeech 19 | element. 20 | 21 | The type provides a set of properties that are by default unset. The TextToSpeech 22 | element will choose the first voice that matches all the set property values. 23 | If no voice is found that matches all criteria, then the voice doesn't change. 24 | 25 | When setting individual properties within this group after the TextToSpeech object 26 | has been initialized, then you have to call the select() method to trigger the 27 | selection of a voice. 28 | 29 | \sa TextToSpeech::voice, TextToSpeech::availableVoices() 30 | */ 31 | 32 | QVoiceSelectorAttached *QVoiceSelectorAttached::qmlAttachedProperties(QObject *obj) 33 | { 34 | QVoiceSelectorAttached *attached = nullptr; 35 | if (QDeclarativeTextToSpeech *tts = qobject_cast(obj)) { 36 | Q_ASSERT(!tts->m_voiceSelector); 37 | attached = new QVoiceSelectorAttached(tts); 38 | tts->m_voiceSelector = attached; 39 | } else { 40 | qCritical("A VoiceSelector can only be attached to a TextToSpeech element!"); 41 | } 42 | return attached; 43 | } 44 | 45 | QVoiceSelectorAttached::QVoiceSelectorAttached(QDeclarativeTextToSpeech *tts) 46 | : QObject(tts), m_tts(tts) 47 | {} 48 | 49 | /*! 50 | \qmlmethod void VoiceSelector::select() 51 | 52 | Activates the selection of the voice based on the specified criteria. 53 | 54 | \note This method only needs to be called if the selection criteria are 55 | modified after the TextToSpeech object has been instantiated. 56 | */ 57 | void QVoiceSelectorAttached::select() 58 | { 59 | m_tts->selectVoice(); 60 | } 61 | 62 | /*! 63 | \qmlproperty variant VoiceSelector::name 64 | \brief This property specifies which name the selected voice should have. 65 | 66 | The property can be a string, or a regular expression. 67 | */ 68 | 69 | QVariant QVoiceSelectorAttached::name() const 70 | { 71 | return m_criteria.value(u"name"_s); 72 | } 73 | 74 | void QVoiceSelectorAttached::setName(const QVariant &name) 75 | { 76 | if (!name.isValid()) { 77 | m_criteria.remove(u"name"_s); 78 | return; 79 | } 80 | 81 | QVariant &m_name = m_criteria[u"name"_s]; 82 | if (m_name == name) 83 | return; 84 | 85 | m_name = name; 86 | emit nameChanged(); 87 | } 88 | 89 | /*! 90 | \qmlproperty enumerator VoiceSelector::gender 91 | \brief This property specifies which \l{QVoice::Gender}{gender} the selected 92 | voice should have. 93 | */ 94 | 95 | QVoice::Gender QVoiceSelectorAttached::gender() const 96 | { 97 | return m_criteria.value(u"gender"_s).value(); 98 | } 99 | 100 | void QVoiceSelectorAttached::setGender(QVoice::Gender gender) 101 | { 102 | QVariant &m_gender = m_criteria[u"gender"_s]; 103 | if (m_gender == gender) 104 | return; 105 | 106 | m_gender = gender; 107 | emit genderChanged(); 108 | } 109 | 110 | /*! 111 | \qmlproperty enumerator VoiceSelector::age 112 | \brief This property specifies which \l{QVoice::Age}{age} the selected voice 113 | should have. 114 | */ 115 | 116 | QVoice::Age QVoiceSelectorAttached::age() const 117 | { 118 | return m_criteria.value(u"age"_s).value(); 119 | } 120 | 121 | void QVoiceSelectorAttached::setAge(QVoice::Age age) 122 | { 123 | QVariant &m_age = m_criteria[u"age"_s]; 124 | if (m_age == age) 125 | return; 126 | m_age = age; 127 | emit ageChanged(); 128 | } 129 | 130 | /*! 131 | \qmlproperty locale VoiceSelector::locale 132 | \brief This property specifies which locale the selected voice should have. 133 | 134 | If this property is set, then both the language and the territory of the 135 | voice need to match. 136 | 137 | \sa language 138 | */ 139 | QLocale QVoiceSelectorAttached::locale() const 140 | { 141 | return m_criteria.value(u"locale"_s).toLocale(); 142 | } 143 | 144 | void QVoiceSelectorAttached::setLocale(const QLocale &locale) 145 | { 146 | QVariant &m_locale = m_criteria[u"locale"_s]; 147 | if (m_locale == locale) 148 | return; 149 | 150 | m_locale = locale; 151 | emit localeChanged(); 152 | } 153 | 154 | /*! 155 | \qmlproperty locale VoiceSelector::language 156 | \brief This property specifies which language the selected voice should have. 157 | 158 | The property is of type locale, but only the language component of the locale 159 | will be considered, the territory will be ignored. 160 | 161 | \sa locale 162 | */ 163 | QLocale QVoiceSelectorAttached::language() const 164 | { 165 | const auto &it = m_criteria.find(u"language"_s); 166 | if (it == m_criteria.end()) 167 | return locale(); 168 | return (*it).value(); 169 | } 170 | 171 | void QVoiceSelectorAttached::setLanguage(const QLocale &language) 172 | { 173 | QVariant &m_language = m_criteria[u"language"_s]; 174 | if (m_language == language) 175 | return; 176 | 177 | m_language = language; 178 | emit languageChanged(); 179 | } 180 | 181 | QT_END_NAMESPACE 182 | -------------------------------------------------------------------------------- /tests/auto/qtexttospeech_qml/tst_texttospeech.qml: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2023 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only 3 | 4 | import QtQuick 5 | 6 | import QtTest 7 | import QtTextToSpeech 8 | 9 | TestCase { 10 | id: testCase 11 | name: "TextToSpeech" 12 | 13 | TextToSpeech { 14 | id: tts 15 | engine: "mock" 16 | } 17 | 18 | // verifies that the mock engine is synchronous by default 19 | function initTestCase() { 20 | compare(tts.state, TextToSpeech.Ready) 21 | } 22 | 23 | Component { 24 | id: defaultEngine 25 | TextToSpeech { 26 | rate: 0.5 27 | volume: 0.8 28 | pitch: 0.1 29 | } 30 | } 31 | 32 | function test_defaultEngine() { 33 | let def = createTemporaryObject(defaultEngine, testCase) 34 | if (!def.engine) 35 | skip("No default engine available on this platform") 36 | else if (def.engine == "speechd") 37 | skip("Older libspeechd versions don't implement attribute getters") 38 | else 39 | console.log("The default tts engine is " + def.engine) 40 | 41 | compare(def.rate, 0.5) 42 | compare(def.volume, 0.8) 43 | compare(def.pitch, 0.1) 44 | } 45 | 46 | function test_availableLocales() { 47 | compare(tts.availableLocales().length, 5) 48 | } 49 | 50 | function test_availableVoices() { 51 | compare(tts.availableVoices().length, 2) 52 | } 53 | 54 | function test_findVoices() { 55 | let bob = tts.findVoices({name: "Bob"}) 56 | compare(bob.length, 1) 57 | let women = tts.findVoices({gender: Voice.Female}) 58 | compare(women.length, 5) 59 | let children = tts.findVoices({age: Voice.Child}) 60 | compare(children.length, 1) 61 | // includes all english speakers, no matter where they're from 62 | let english = tts.findVoices({language: Qt.locale("en")}) 63 | compare(english.length, 4) 64 | let bokmalers = tts.findVoices({locale: Qt.locale("NO")}) 65 | compare(bokmalers.length, 2) 66 | let nynorskers = tts.findVoices({locale: Qt.locale("nn-NO")}) 67 | compare(nynorskers.length, 2) 68 | 69 | let englishWomen = tts.findVoices({ 70 | language: Qt.locale("en"), 71 | gender: Voice.Female, 72 | age: Voice.Adult 73 | }); 74 | compare(englishWomen.length, 1) 75 | } 76 | 77 | Component { 78 | id: lateEngine 79 | TextToSpeech { 80 | rate: 0.5 81 | volume: 0.8 82 | pitch: 0.1 83 | engine: "mock" 84 | } 85 | } 86 | 87 | function test_lateEngine() { 88 | let tts = createTemporaryObject(lateEngine, testCase) 89 | tryCompare(tts, "state", TextToSpeech.Ready) 90 | 91 | compare(tts.rate, 0.5) 92 | compare(tts.volume, 0.8) 93 | compare(tts.pitch, 0.1) 94 | compare(tts.engine, "mock") 95 | 96 | tts.engine = "" 97 | // If there is no default engine, then we use mock 98 | if (!tts.engine) 99 | tts.engine = "mock"; 100 | else if (tts.engine == "speechd") 101 | skip("Older libspeechd versions don't implement attribute getters") 102 | 103 | compare(tts.rate, 0.5) 104 | compare(tts.volume, 0.8) 105 | compare(tts.pitch, 0.1) 106 | } 107 | 108 | Component { 109 | id: name_selector 110 | TextToSpeech { 111 | engine: "mock" 112 | engineParameters: { 113 | "delayedInitialization": true 114 | } 115 | 116 | VoiceSelector.name: "Ingvild" 117 | } 118 | } 119 | 120 | Component { 121 | id: genderLanguage_selector 122 | TextToSpeech { 123 | engine: "mock" 124 | engineParameters: { 125 | "delayedInitialization": true 126 | } 127 | 128 | VoiceSelector.gender: Voice.Female 129 | VoiceSelector.language: Qt.locale("en") 130 | } 131 | } 132 | 133 | function test_voiceSelector() { 134 | var selector = createTemporaryObject(name_selector, testCase) 135 | tryCompare(selector, "state", TextToSpeech.Ready) 136 | 137 | compare(selector.voice.name, "Ingvild") 138 | 139 | // there is no way to get to QLocale::English from QML 140 | let EnglishID = 75 141 | 142 | selector = createTemporaryObject(genderLanguage_selector, testCase) 143 | tryCompare(selector, "state", TextToSpeech.Ready) 144 | 145 | verify(["Anne", "Mary"].includes(selector.voice.name)) 146 | let oldName = selector.voice.name 147 | compare(selector.voice.gender, Voice.Female) 148 | compare(selector.voice.language, EnglishID) 149 | 150 | // overwrite after initialization 151 | selector.VoiceSelector.gender = Voice.Male 152 | // no change until select is called 153 | compare(selector.voice.name, oldName) 154 | selector.VoiceSelector.select() 155 | 156 | compare(selector.voice.name, "Bob") 157 | compare(selector.voice.gender, Voice.Male) 158 | compare(selector.voice.language, EnglishID) 159 | } 160 | 161 | function test_delayedSelection() { 162 | var selector = createTemporaryObject(name_selector, testCase) 163 | tryCompare(selector, "state", TextToSpeech.Ready) 164 | 165 | selector.VoiceSelector.gender = Voice.Female 166 | selector.VoiceSelector.name = "Kjersti" 167 | selector.VoiceSelector.select() 168 | 169 | compare(selector.voice.name, "Kjersti") 170 | } 171 | 172 | function test_regularExpressionName() { 173 | var selector = createTemporaryObject(name_selector, testCase) 174 | tryCompare(selector, "state", TextToSpeech.Ready) 175 | 176 | selector.VoiceSelector.name = /K.*/ 177 | selector.VoiceSelector.select() 178 | 179 | verify(["Kjersti", "Kari"].includes(selector.voice.name)) 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /examples/speech/hello_speak/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2024 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause 3 | 4 | #include "mainwindow.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | using namespace Qt::StringLiterals; 11 | 12 | MainWindow::MainWindow(QWidget *parent) 13 | : QMainWindow(parent) 14 | { 15 | ui.setupUi(this); 16 | QLoggingCategory::setFilterRules(u"qt.speech.tts=true \n qt.speech.tts.*=true"_s); 17 | 18 | // Populate engine selection list 19 | ui.engine->addItem(u"Default"_s, u"default"_s); 20 | const auto engines = QTextToSpeech::availableEngines(); 21 | for (const QString &engine : engines) 22 | ui.engine->addItem(engine, engine); 23 | ui.engine->setCurrentIndex(0); 24 | engineSelected(0); 25 | 26 | connect(ui.pitch, &QSlider::valueChanged, this, &MainWindow::setPitch); 27 | connect(ui.rate, &QSlider::valueChanged, this, &MainWindow::setRate); 28 | connect(ui.volume, &QSlider::valueChanged, this, &MainWindow::setVolume); 29 | connect(ui.engine, &QComboBox::currentIndexChanged, this, &MainWindow::engineSelected); 30 | connect(ui.language, &QComboBox::currentIndexChanged, this, &MainWindow::languageSelected); 31 | connect(ui.voice, &QComboBox::currentIndexChanged, this, &MainWindow::voiceSelected); 32 | } 33 | 34 | void MainWindow::setRate(int rate) 35 | { 36 | m_speech->setRate(rate / 10.0); 37 | } 38 | 39 | void MainWindow::setPitch(int pitch) 40 | { 41 | m_speech->setPitch(pitch / 10.0); 42 | } 43 | 44 | void MainWindow::setVolume(int volume) 45 | { 46 | m_speech->setVolume(volume / 100.0); 47 | } 48 | 49 | //! [stateChanged] 50 | void MainWindow::stateChanged(QTextToSpeech::State state) 51 | { 52 | switch (state) { 53 | case QTextToSpeech::Speaking: 54 | ui.statusbar->showMessage(tr("Speech started...")); 55 | break; 56 | case QTextToSpeech::Ready: 57 | ui.statusbar->showMessage(tr("Speech stopped..."), 2000); 58 | break; 59 | case QTextToSpeech::Paused: 60 | ui.statusbar->showMessage(tr("Speech paused...")); 61 | break; 62 | default: 63 | ui.statusbar->showMessage(tr("Speech error!")); 64 | break; 65 | } 66 | 67 | ui.pauseButton->setEnabled(state == QTextToSpeech::Speaking); 68 | ui.resumeButton->setEnabled(state == QTextToSpeech::Paused); 69 | ui.stopButton->setEnabled(state == QTextToSpeech::Speaking || state == QTextToSpeech::Paused); 70 | } 71 | //! [stateChanged] 72 | 73 | void MainWindow::engineSelected(int index) 74 | { 75 | const QString engineName = ui.engine->itemData(index).toString(); 76 | 77 | delete m_speech; 78 | m_speech = engineName == u"default" 79 | ? new QTextToSpeech(this) 80 | : new QTextToSpeech(engineName, this); 81 | 82 | // some engines initialize asynchronously 83 | if (m_speech->state() == QTextToSpeech::Ready) { 84 | onEngineReady(); 85 | } else { 86 | connect(m_speech, &QTextToSpeech::stateChanged, this, &MainWindow::onEngineReady, 87 | Qt::SingleShotConnection); 88 | } 89 | } 90 | 91 | static bool localeLessThan(const QLocale &l1, const QLocale &l2) 92 | { 93 | return l1.name().compare(l2.name()) < 0; 94 | } 95 | 96 | void MainWindow::onEngineReady() 97 | { 98 | if (m_speech->state() != QTextToSpeech::Ready) { 99 | stateChanged(m_speech->state()); 100 | return; 101 | } 102 | 103 | const bool hasPauseResume = m_speech->engineCapabilities() 104 | & QTextToSpeech::Capability::PauseResume; 105 | ui.pauseButton->setVisible(hasPauseResume); 106 | ui.resumeButton->setVisible(hasPauseResume); 107 | 108 | // Block signals of the languages combobox while populating 109 | QSignalBlocker blocker(ui.language); 110 | 111 | ui.language->clear(); 112 | QList locales = m_speech->availableLocales(); 113 | std::stable_sort(locales.begin(), locales.end(), localeLessThan); 114 | 115 | QLocale current = m_speech->locale(); 116 | for (const QLocale &locale : std::as_const(locales)) { 117 | QString name(u"%1 (%2)"_s 118 | .arg(QLocale::languageToString(locale.language()), 119 | QLocale::territoryToString(locale.territory()))); 120 | QVariant localeVariant(locale); 121 | ui.language->addItem(name, localeVariant); 122 | if (locale.name() == current.name()) 123 | current = locale; 124 | } 125 | setRate(ui.rate->value()); 126 | setPitch(ui.pitch->value()); 127 | setVolume(ui.volume->value()); 128 | //! [say] 129 | connect(ui.speakButton, &QPushButton::clicked, m_speech, [this]{ 130 | m_speech->say(ui.plainTextEdit->toPlainText()); 131 | }); 132 | //! [say] 133 | //! [stop] 134 | connect(ui.stopButton, &QPushButton::clicked, m_speech, [this]{ 135 | m_speech->stop(); 136 | }); 137 | //! [stop] 138 | //! [pause] 139 | connect(ui.pauseButton, &QPushButton::clicked, m_speech, [this]{ 140 | m_speech->pause(); 141 | }); 142 | //! [pause] 143 | //! [resume] 144 | connect(ui.resumeButton, &QPushButton::clicked, m_speech, &QTextToSpeech::resume); 145 | //! [resume] 146 | 147 | connect(m_speech, &QTextToSpeech::stateChanged, this, &MainWindow::stateChanged); 148 | connect(m_speech, &QTextToSpeech::localeChanged, this, &MainWindow::localeChanged); 149 | 150 | blocker.unblock(); 151 | 152 | localeChanged(current); 153 | } 154 | 155 | void MainWindow::languageSelected(int language) 156 | { 157 | QLocale locale = ui.language->itemData(language).toLocale(); 158 | m_speech->setLocale(locale); 159 | } 160 | 161 | void MainWindow::voiceSelected(int index) 162 | { 163 | m_speech->setVoice(m_voices.at(index)); 164 | } 165 | 166 | void MainWindow::localeChanged(const QLocale &locale) 167 | { 168 | QVariant localeVariant(locale); 169 | ui.language->setCurrentIndex(ui.language->findData(localeVariant)); 170 | 171 | QSignalBlocker blocker(ui.voice); 172 | 173 | ui.voice->clear(); 174 | 175 | m_voices = m_speech->availableVoices(); 176 | QVoice currentVoice = m_speech->voice(); 177 | for (const QVoice &voice : std::as_const(m_voices)) { 178 | ui.voice->addItem(u"%1 - %2 - %3"_s 179 | .arg(voice.name(), QVoice::genderName(voice.gender()), 180 | QVoice::ageName(voice.age()))); 181 | if (voice.name() == currentVoice.name()) 182 | ui.voice->setCurrentIndex(ui.voice->count() - 1); 183 | } 184 | } 185 | 186 | MainWindow::~MainWindow() 187 | { 188 | m_speech->disconnect(this); 189 | } 190 | -------------------------------------------------------------------------------- /examples/speech/quickspeech/Main.qml: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause 3 | 4 | import QtQuick 5 | import QtQuick.Controls 6 | import QtQuick.Layouts 7 | import QtTextToSpeech 8 | 9 | ApplicationWindow { 10 | id: root 11 | visible: true 12 | title: qsTr("Text to Speech") 13 | minimumWidth: inputForm.implicitWidth 14 | minimumHeight: inputForm.implicitHeight + footer.implicitHeight 15 | 16 | //! [initialize] 17 | TextToSpeech { 18 | id: tts 19 | volume: volumeSlider.value 20 | pitch: pitchSlider.value 21 | rate: rateSlider.value 22 | //! [initialize] 23 | 24 | //! [stateChanged] 25 | onStateChanged: updateStateLabel(state) 26 | 27 | function updateStateLabel(state) 28 | { 29 | switch (state) { 30 | case TextToSpeech.Ready: 31 | statusLabel.text = qsTr("Ready") 32 | break 33 | case TextToSpeech.Speaking: 34 | statusLabel.text = qsTr("Speaking") 35 | break 36 | case TextToSpeech.Paused: 37 | statusLabel.text = qsTr("Paused...") 38 | break 39 | case TextToSpeech.Error: 40 | statusLabel.text = qsTr("Error!") 41 | break 42 | } 43 | } 44 | //! [stateChanged] 45 | 46 | //! [sayingWord] 47 | onSayingWord: (word, id, start, length)=> { 48 | input.select(start, start + length) 49 | } 50 | //! [sayingWord] 51 | } 52 | 53 | ColumnLayout { 54 | anchors.fill: parent 55 | anchors.margins: 8 56 | id: inputForm 57 | 58 | TextArea { 59 | id: input 60 | wrapMode: TextEdit.WordWrap 61 | text: qsTr("Hello, world!") 62 | Layout.fillWidth: true 63 | Layout.minimumHeight: implicitHeight 64 | font.pointSize: 24 65 | } 66 | //! [say0] 67 | RowLayout { 68 | Button { 69 | text: qsTr("Speak") 70 | enabled: [TextToSpeech.Paused, TextToSpeech.Ready].includes(tts.state) 71 | onClicked: { 72 | let voices = tts.availableVoices() 73 | tts.voice = voices[voicesComboBox.currentIndex] 74 | tts.say(input.text) 75 | } 76 | } 77 | //! [say0] 78 | //! [pause] 79 | Button { 80 | text: qsTr("Pause") 81 | enabled: tts.state == TextToSpeech.Speaking 82 | onClicked: tts.pause() 83 | visible: tts.engineCapabilities & TextToSpeech.Capabilities.PauseResume 84 | } 85 | //! [pause] 86 | //! [resume] 87 | Button { 88 | text: qsTr("Resume") 89 | enabled: tts.state == TextToSpeech.Paused 90 | onClicked: tts.resume() 91 | visible: tts.engineCapabilities & TextToSpeech.Capabilities.PauseResume 92 | } 93 | //! [resume] 94 | //! [stop] 95 | Button { 96 | text: qsTr("Stop") 97 | enabled: [TextToSpeech.Speaking, TextToSpeech.Paused].includes(tts.state) 98 | onClicked: tts.stop() 99 | } 100 | //! [stop] 101 | } 102 | 103 | GridLayout { 104 | columns: 2 105 | 106 | Label { 107 | text: qsTr("Engine:") 108 | } 109 | ComboBox { 110 | id: enginesComboBox 111 | Layout.fillWidth: true 112 | model: tts.availableEngines() 113 | onActivated: { 114 | tts.engine = textAt(currentIndex) 115 | updateLocales() 116 | updateVoices() 117 | } 118 | } 119 | Label { 120 | text: qsTr("Locale:") 121 | } 122 | ComboBox { 123 | id: localesComboBox 124 | Layout.fillWidth: true 125 | onActivated: { 126 | let locales = tts.availableLocales() 127 | tts.locale = locales[currentIndex] 128 | updateVoices() 129 | } 130 | } 131 | Label { 132 | text: qsTr("Voice:") 133 | } 134 | ComboBox { 135 | id: voicesComboBox 136 | Layout.fillWidth: true 137 | } 138 | Label { 139 | text: qsTr("Volume:") 140 | } 141 | Slider { 142 | id: volumeSlider 143 | from: 0 144 | to: 1.0 145 | stepSize: 0.2 146 | value: 0.8 147 | Layout.fillWidth: true 148 | } 149 | Label { 150 | text: qsTr("Pitch:") 151 | } 152 | Slider { 153 | id: pitchSlider 154 | from: -1.0 155 | to: 1.0 156 | stepSize: 0.5 157 | value: 0 158 | Layout.fillWidth: true 159 | } 160 | Label { 161 | text: qsTr("Rate:") 162 | } 163 | Slider { 164 | id: rateSlider 165 | from: -1.0 166 | to: 1.0 167 | stepSize: 0.5 168 | value: 0 169 | Layout.fillWidth: true 170 | } 171 | } 172 | } 173 | footer: Label { 174 | id: statusLabel 175 | } 176 | 177 | Component.onCompleted: { 178 | enginesComboBox.currentIndex = tts.availableEngines().indexOf(tts.engine) 179 | // some engines initialize asynchronously 180 | if (tts.state == TextToSpeech.Ready) { 181 | engineReady() 182 | } else { 183 | tts.stateChanged.connect(root.engineReady) 184 | } 185 | 186 | tts.updateStateLabel(tts.state) 187 | } 188 | 189 | function engineReady() { 190 | tts.stateChanged.disconnect(root.engineReady) 191 | if (tts.state != TextToSpeech.Ready) { 192 | tts.updateStateLabel(tts.state) 193 | return; 194 | } 195 | updateLocales() 196 | updateVoices() 197 | } 198 | 199 | function updateLocales() { 200 | let allLocales = tts.availableLocales().map((locale) => locale.nativeLanguageName) 201 | let currentLocaleIndex = allLocales.indexOf(tts.locale.nativeLanguageName) 202 | localesComboBox.model = allLocales 203 | localesComboBox.currentIndex = currentLocaleIndex 204 | } 205 | 206 | function updateVoices() { 207 | voicesComboBox.model = tts.availableVoices().map((voice) => voice.name) 208 | let indexOfVoice = tts.availableVoices().indexOf(tts.voice) 209 | voicesComboBox.currentIndex = indexOfVoice 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/plugins/tts/flite/qtexttospeech_flite.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qtexttospeech_flite.h" 6 | 7 | #include 8 | #include 9 | 10 | QT_BEGIN_NAMESPACE 11 | 12 | using namespace Qt::StringLiterals; 13 | 14 | QTextToSpeechEngineFlite::QTextToSpeechEngineFlite(const QVariantMap ¶meters, QObject *parent) 15 | : QTextToSpeechEngine(parent) 16 | { 17 | QAudioDevice audioDevice; 18 | if (const auto it = parameters.find(u"audioDevice"_s); it != parameters.end()) 19 | audioDevice = (*it).value(); 20 | else 21 | audioDevice = QMediaDevices::defaultAudioOutput(); 22 | 23 | if (audioDevice.isNull()) { 24 | m_errorReason = QTextToSpeech::ErrorReason::Playback; 25 | m_errorString = QCoreApplication::translate("QTextToSpeech", "No audio device available"); 26 | } 27 | m_processor = std::make_unique(audioDevice); 28 | 29 | // Connect processor to engine for state changes and error 30 | connect(m_processor.get(), &QTextToSpeechProcessorFlite::stateChanged, 31 | this, &QTextToSpeechEngineFlite::changeState); 32 | connect(m_processor.get(), &QTextToSpeechProcessorFlite::errorOccurred, this, 33 | &QTextToSpeechEngineFlite::setError); 34 | connect(m_processor.get(), &QTextToSpeechProcessorFlite::sayingWord, this, 35 | &QTextToSpeechEngine::sayingWord); 36 | connect(m_processor.get(), &QTextToSpeechProcessorFlite::synthesized, this, 37 | &QTextToSpeechEngine::synthesized); 38 | 39 | // Read voices from processor before moving it to a separate thread 40 | const QList voices = m_processor->voices(); 41 | 42 | int voiceIndex = 0; 43 | for (const QTextToSpeechProcessorFlite::VoiceInfo &voiceInfo : voices) { 44 | const QLocale locale(voiceInfo.locale); 45 | const QVoice voice = QTextToSpeechEngine::createVoice(voiceInfo.name, locale, 46 | voiceInfo.gender, voiceInfo.age, 47 | QVariant(voiceInfo.id)); 48 | m_voices.insert(locale, voice); 49 | // Use the first available locale/voice as a fallback 50 | if (voiceIndex == 0) 51 | m_voice = voice; 52 | ++voiceIndex; 53 | } 54 | 55 | if (voiceIndex) { 56 | m_state = QTextToSpeech::Ready; 57 | m_thread.setObjectName("QTextToSpeechEngineFlite"); 58 | m_processor->moveToThread(&m_thread); 59 | m_thread.start(); 60 | m_thread.setPriority(QThread::HighestPriority); // we feed data to the audio sink 61 | } else { 62 | m_errorReason = QTextToSpeech::ErrorReason::Configuration; 63 | m_errorString = QCoreApplication::translate("QTextToSpeech", "No voices available"); 64 | } 65 | } 66 | 67 | QTextToSpeechEngineFlite::~QTextToSpeechEngineFlite() 68 | { 69 | if (m_processor->thread() != thread()) { 70 | QMetaObject::invokeMethod(m_processor.get(), [&] { 71 | m_processor.reset(); // ensure destruction on the correct thread 72 | }, Qt::BlockingQueuedConnection); 73 | } 74 | 75 | m_thread.exit(); 76 | m_thread.wait(); 77 | } 78 | 79 | QList QTextToSpeechEngineFlite::availableLocales() const 80 | { 81 | return m_voices.uniqueKeys(); 82 | } 83 | 84 | QList QTextToSpeechEngineFlite::availableVoices() const 85 | { 86 | return m_voices.values(m_voice.locale()); 87 | } 88 | 89 | void QTextToSpeechEngineFlite::say(const QString &text) 90 | { 91 | QMetaObject::invokeMethod(m_processor.get(), "say", Qt::QueuedConnection, Q_ARG(QString, text), 92 | Q_ARG(int, voiceData(voice()).toInt()), Q_ARG(double, pitch()), 93 | Q_ARG(double, rate()), Q_ARG(double, volume())); 94 | } 95 | 96 | void QTextToSpeechEngineFlite::synthesize(const QString &text) 97 | { 98 | QMetaObject::invokeMethod(m_processor.get(), "synthesize", Qt::QueuedConnection, Q_ARG(QString, text), 99 | Q_ARG(int, voiceData(voice()).toInt()), Q_ARG(double, pitch()), 100 | Q_ARG(double, rate()), Q_ARG(double, volume())); 101 | } 102 | 103 | void QTextToSpeechEngineFlite::stop(QTextToSpeech::BoundaryHint boundaryHint) 104 | { 105 | QMetaObject::invokeMethod(m_processor.get(), &QTextToSpeechProcessorFlite::stop, 106 | Qt::QueuedConnection, boundaryHint); 107 | } 108 | 109 | void QTextToSpeechEngineFlite::pause(QTextToSpeech::BoundaryHint boundaryHint) 110 | { 111 | QMetaObject::invokeMethod(m_processor.get(), &QTextToSpeechProcessorFlite::pause, 112 | Qt::QueuedConnection, boundaryHint); 113 | } 114 | 115 | void QTextToSpeechEngineFlite::resume() 116 | { 117 | QMetaObject::invokeMethod(m_processor.get(), &QTextToSpeechProcessorFlite::resume, Qt::QueuedConnection); 118 | } 119 | 120 | double QTextToSpeechEngineFlite::rate() const 121 | { 122 | return m_rate; 123 | } 124 | 125 | bool QTextToSpeechEngineFlite::setRate(double rate) 126 | { 127 | if (m_rate == rate) 128 | return false; 129 | 130 | m_rate = rate; 131 | return true; 132 | } 133 | 134 | double QTextToSpeechEngineFlite::pitch() const 135 | { 136 | return m_pitch; 137 | } 138 | 139 | bool QTextToSpeechEngineFlite::setPitch(double pitch) 140 | { 141 | if (m_pitch == pitch) 142 | return false; 143 | 144 | m_pitch = pitch; 145 | return true; 146 | } 147 | 148 | QLocale QTextToSpeechEngineFlite::locale() const 149 | { 150 | return m_voice.locale(); 151 | } 152 | 153 | bool QTextToSpeechEngineFlite::setLocale(const QLocale &locale) 154 | { 155 | const auto &voices = m_voices.values(locale); 156 | if (voices.isEmpty()) 157 | return false; 158 | // The list returned by QMultiHash::values is reversed 159 | setVoice(voices.last()); 160 | return true; 161 | } 162 | 163 | double QTextToSpeechEngineFlite::volume() const 164 | { 165 | return m_volume; 166 | } 167 | 168 | bool QTextToSpeechEngineFlite::setVolume(double volume) 169 | { 170 | if (m_volume == volume) 171 | return false; 172 | 173 | m_volume = volume; 174 | return true; 175 | } 176 | 177 | QVoice QTextToSpeechEngineFlite::voice() const 178 | { 179 | return m_voice; 180 | } 181 | 182 | bool QTextToSpeechEngineFlite::setVoice(const QVoice &voice) 183 | { 184 | QLocale locale = m_voices.key(voice); // returns default locale if not found, so 185 | if (!m_voices.contains(locale, voice)) { 186 | qWarning() << "Voice" << voice << "is not supported by this engine"; 187 | return false; 188 | } 189 | 190 | m_voice = voice; 191 | return true; 192 | } 193 | 194 | void QTextToSpeechEngineFlite::changeState(QTextToSpeech::State newState) 195 | { 196 | if (newState != m_state) { 197 | m_state = newState; 198 | emit stateChanged(newState); 199 | } 200 | } 201 | 202 | QTextToSpeech::State QTextToSpeechEngineFlite::state() const 203 | { 204 | return m_state; 205 | } 206 | 207 | QTextToSpeech::ErrorReason QTextToSpeechEngineFlite::errorReason() const 208 | { 209 | return m_errorReason; 210 | } 211 | 212 | QString QTextToSpeechEngineFlite::errorString() const 213 | { 214 | return m_errorString; 215 | } 216 | 217 | void QTextToSpeechEngineFlite::setError(QTextToSpeech::ErrorReason error, const QString &errorString) 218 | { 219 | m_errorReason = error; 220 | m_errorString = errorString; 221 | changeState(QTextToSpeech::Error); 222 | emit errorOccurred(error, errorString); 223 | } 224 | 225 | QT_END_NAMESPACE 226 | -------------------------------------------------------------------------------- /LICENSES/LGPL-3.0-only.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /src/tts/qvoice.cpp: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2022 The Qt Company Ltd. 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only 3 | // Qt-Security score:significant reason:default 4 | 5 | #include "qvoice.h" 6 | #include "qvoice_p.h" 7 | #include "qtexttospeech.h" 8 | 9 | QT_BEGIN_NAMESPACE 10 | 11 | QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QVoicePrivate) 12 | 13 | /*! 14 | \class QVoice 15 | \brief The QVoice class represents a particular voice. 16 | \inmodule QtTextToSpeech 17 | 18 | To get a voice that is supported by the current text-to-speech engine, 19 | use \l QTextToSpeech::availableVoices() or \l QTextToSpeech::findVoices(). 20 | */ 21 | 22 | /*! 23 | \qmlvaluetype voice 24 | \inqmlmodule QtTextToSpeech 25 | \brief The voice type represents a particular voice. 26 | 27 | To get a voice that is supported by the current text-to-speech engine, 28 | use \l TextToSpeech::availableVoices(). 29 | */ 30 | 31 | /*! 32 | \enum QVoice::Age 33 | 34 | The age of a voice. 35 | 36 | \value Child Voice of a child 37 | \value Teenager Voice of a teenager 38 | \value Adult Voice of an adult 39 | \value Senior Voice of a senior 40 | \value Other Voice of unknown age 41 | */ 42 | 43 | /*! 44 | \enum QVoice::Gender 45 | 46 | The gender of a voice. 47 | 48 | \value Male Voice of a male 49 | \value Female Voice of a female 50 | \value Unknown Voice of unknown gender 51 | */ 52 | 53 | /*! 54 | Constructs an empty QVoice. 55 | 56 | Application code cannot construct arbitrary voice instances. 57 | Use \l{QTextToSpeech::availableVoices()} or \l{QTextToSpeech::findVoices()} 58 | instead to select a supported voice. 59 | */ 60 | QVoice::QVoice() 61 | : d(nullptr) 62 | { 63 | } 64 | 65 | /*! 66 | Copy-constructs a QVoice from \a other. 67 | */ 68 | QVoice::QVoice(const QVoice &other) noexcept 69 | : d(other.d) 70 | {} 71 | 72 | /*! 73 | Destroys the QVoice instance. 74 | */ 75 | QVoice::~QVoice() 76 | {} 77 | 78 | /*! 79 | \fn QVoice::QVoice(QVoice &&other) 80 | 81 | Constructs a QVoice object by moving from \a other. 82 | */ 83 | 84 | /*! 85 | \fn QVoice &QVoice::operator=(QVoice &&other) 86 | Moves \a other into this QVoice object. 87 | */ 88 | 89 | /*! 90 | Assigns \a other to this QVoice object. 91 | */ 92 | QVoice &QVoice::operator=(const QVoice &other) noexcept 93 | { 94 | d = other.d; 95 | return *this; 96 | } 97 | 98 | /*! 99 | \internal 100 | */ 101 | QVoice::QVoice(const QString &name, const QLocale &locale, Gender gender, 102 | Age age, const QVariant &data) 103 | :d(new QVoicePrivate(name, locale, gender, age, data)) 104 | { 105 | } 106 | 107 | 108 | /*! 109 | \internal 110 | Compares all attributes of this voice with \a other. 111 | Returns \c true if all of them match. 112 | */ 113 | bool QVoice::isEqual(const QVoice &other) const noexcept 114 | { 115 | if (d == other.d) 116 | return true; 117 | if (!d || !other.d) 118 | return false; 119 | 120 | return d->data == other.d->data 121 | && d->name == other.d->name 122 | && d->locale == other.d->locale 123 | && d->gender == other.d->gender 124 | && d->age == other.d->age; 125 | } 126 | 127 | /*! 128 | \fn void QVoice::swap(QVoice &other) noexcept 129 | \since 6.4 130 | 131 | Swaps \a other with this voice. This operation is very fast and never fails. 132 | */ 133 | 134 | /*! 135 | \fn bool QVoice::operator==(const QVoice &lhs, const QVoice &rhs) 136 | \return whether the \a lhs voice and the \a rhs voice are identical. 137 | 138 | Two voices are identical if \l name, \l locale, \l gender, and \l age 139 | are identical, and if they belong to the same text-to-speech engine. 140 | */ 141 | 142 | /*! 143 | \fn bool QVoice::operator!=(const QVoice &lhs, const QVoice &rhs) 144 | \return whether the \a lhs voice and the \a rhs voice are different. 145 | */ 146 | 147 | /*! 148 | \fn QDataStream &QVoice::operator<<(QDataStream &stream, const QVoice &voice) 149 | \since 6.4 150 | 151 | Serializes \a voice to data stream \a stream. 152 | 153 | \sa {Serializing Qt Data Types} 154 | */ 155 | 156 | /*! 157 | \fn QDataStream &QVoice::operator>>(QDataStream &stream, QVoice &voice) 158 | \since 6.4 159 | 160 | Deserializes \a voice from data stream \a stream. 161 | 162 | \sa {Serializing Qt Data Types} 163 | */ 164 | 165 | /*! 166 | \qmlproperty string voice::name 167 | \brief This property holds the name of the voice. 168 | */ 169 | 170 | /*! 171 | \property QVoice::name 172 | \brief the name of a voice 173 | */ 174 | QString QVoice::name() const 175 | { 176 | return d ? d->name : QString(); 177 | } 178 | 179 | /*! 180 | \qmlproperty enumerator voice::language 181 | \brief This property holds the language of the voice. 182 | \since 6.6 183 | 184 | This is the \l{QLocale::}{language} attribute of the voice's \l locale. 185 | */ 186 | 187 | /*! 188 | \property QVoice::language 189 | \brief the language of the voice 190 | \since 6.6 191 | 192 | This is the \l{QLocale::}{language} attribute of the voice's \l locale. 193 | */ 194 | 195 | /*! 196 | \qmlproperty locale voice::locale 197 | \brief This property holds the locale of the voice. 198 | 199 | The locale includes the language and the territory (i.e. accent or dialect) 200 | of the voice. 201 | 202 | \a language 203 | */ 204 | 205 | /*! 206 | \property QVoice::locale 207 | \brief the locale of the voice 208 | \since 6.4 209 | 210 | The locale includes the language and the territory (i.e. accent or dialect) 211 | of the voice. 212 | */ 213 | QLocale QVoice::locale() const 214 | { 215 | return d ? d->locale : QLocale(); 216 | } 217 | 218 | /*! 219 | \qmlproperty enumeration voice::gender 220 | \brief This property holds the gender of the voice. 221 | 222 | \sa QVoice::Gender 223 | */ 224 | 225 | /*! 226 | \property QVoice::gender 227 | \brief the gender of a voice 228 | */ 229 | QVoice::Gender QVoice::gender() const 230 | { 231 | return d ? d->gender : QVoice::Unknown; 232 | } 233 | 234 | /*! 235 | \qmlproperty enumeration voice::age 236 | \brief This property holds the age of the voice. 237 | 238 | \sa QVoice::Age 239 | */ 240 | 241 | /*! 242 | \property QVoice::age 243 | \brief the age of a voice 244 | */ 245 | QVoice::Age QVoice::age() const 246 | { 247 | return d ? d->age : QVoice::Other; 248 | } 249 | 250 | /*! 251 | \internal 252 | */ 253 | QVariant QVoice::data() const 254 | { 255 | return d ? d->data : QVariant(); 256 | } 257 | 258 | /*!̈́ 259 | Returns the \a gender name of a voice. 260 | */ 261 | QString QVoice::genderName(QVoice::Gender gender) 262 | { 263 | QString retval; 264 | switch (gender) { 265 | case QVoice::Male: 266 | retval = QTextToSpeech::tr("Male", "Gender of a voice"); 267 | break; 268 | case QVoice::Female: 269 | retval = QTextToSpeech::tr("Female", "Gender of a voice"); 270 | break; 271 | case QVoice::Unknown: 272 | retval = QTextToSpeech::tr("Unknown Gender", "Voice gender is unknown"); 273 | break; 274 | } 275 | return retval; 276 | } 277 | 278 | /*! 279 | Returns a string representing the \a age class of a voice. 280 | */ 281 | QString QVoice::ageName(QVoice::Age age) 282 | { 283 | QString retval; 284 | switch (age) { 285 | case QVoice::Child: 286 | retval = QTextToSpeech::tr("Child", "Age of a voice"); 287 | break; 288 | case QVoice::Teenager: 289 | retval = QTextToSpeech::tr("Teenager", "Age of a voice"); 290 | break; 291 | case QVoice::Adult: 292 | retval = QTextToSpeech::tr("Adult", "Age of a voice"); 293 | break; 294 | case QVoice::Senior: 295 | retval = QTextToSpeech::tr("Senior", "Age of a voice"); 296 | break; 297 | case QVoice::Other: 298 | retval = QTextToSpeech::tr("Other Age", "Unknown age of a voice"); 299 | break; 300 | } 301 | return retval; 302 | } 303 | 304 | #ifndef QT_NO_DATASTREAM 305 | QDataStream &QVoice::writeTo(QDataStream &stream) const 306 | { 307 | stream << name() << locale() << int(gender()) << int(age()) << data(); 308 | return stream; 309 | } 310 | 311 | QDataStream &QVoice::readFrom(QDataStream &stream) 312 | { 313 | if (!d) 314 | d.reset(new QVoicePrivate); 315 | 316 | int g, a; 317 | stream >> d->name >> d->locale >> g >> a >> d->data; 318 | d->gender = Gender(g); 319 | d->age = Age(a); 320 | return stream; 321 | } 322 | #endif 323 | 324 | #ifndef QT_NO_DEBUG_STREAM 325 | 326 | /*! 327 | \fn QDebug QVoice::operator<<(QDebug debug, const QVoice &voice) 328 | \since 6.4 329 | 330 | Writes information about \a voice to the \a debug stream. 331 | 332 | \sa QDebug 333 | */ 334 | QDebug operator<<(QDebug dbg, const QVoice &voice) 335 | { 336 | QDebugStateSaver state(dbg); 337 | dbg.noquote().nospace(); 338 | dbg << "QVoice(name: " << voice.name() 339 | << ", locale: " << voice.locale() 340 | << ", gender: " << QVoice::genderName(voice.gender()) 341 | << ", age: " << QVoice::ageName(voice.age()) 342 | << "; data: " << voice.data() 343 | << ")"; 344 | return dbg; 345 | } 346 | #endif 347 | 348 | QT_END_NAMESPACE 349 | -------------------------------------------------------------------------------- /examples/speech/hello_speak/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 551 10 | 448 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 0 23 | 0 24 | 25 | 26 | 27 | Hello QtTextToSpeech, 28 | this is an example text in English. 29 | 30 | QtSpeech is a library that makes text to speech easy with Qt. 31 | Done, over and out. 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 0 42 | 0 43 | 44 | 45 | 46 | Engine 47 | 48 | 49 | Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 0 58 | 0 59 | 60 | 61 | 62 | Pitch: 63 | 64 | 65 | Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 0 74 | 0 75 | 76 | 77 | 78 | &Language: 79 | 80 | 81 | Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter 82 | 83 | 84 | language 85 | 86 | 87 | 88 | 89 | 90 | 91 | -10 92 | 93 | 94 | 10 95 | 96 | 97 | 1 98 | 99 | 100 | Qt::Orientation::Horizontal 101 | 102 | 103 | 104 | 105 | 106 | 107 | Voice name: 108 | 109 | 110 | Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter 111 | 112 | 113 | 114 | 115 | 116 | 117 | 100 118 | 119 | 120 | 5 121 | 122 | 123 | 20 124 | 125 | 126 | 70 127 | 128 | 129 | Qt::Orientation::Horizontal 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 0 138 | 0 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 0 151 | 0 152 | 153 | 154 | 155 | Rate: 156 | 157 | 158 | Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 0 167 | 0 168 | 169 | 170 | 171 | Volume: 172 | 173 | 174 | Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter 175 | 176 | 177 | 178 | 179 | 180 | 181 | -10 182 | 183 | 184 | 10 185 | 186 | 187 | Qt::Orientation::Horizontal 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 0 196 | 0 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | Speak 209 | 210 | 211 | 212 | 213 | 214 | 215 | false 216 | 217 | 218 | Pause 219 | 220 | 221 | 222 | 223 | 224 | 225 | false 226 | 227 | 228 | Resume 229 | 230 | 231 | 232 | 233 | 234 | 235 | Stop 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | Qt::Orientation::Vertical 245 | 246 | 247 | 248 | 20 249 | 40 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | plainTextEdit 260 | speakButton 261 | pauseButton 262 | resumeButton 263 | stopButton 264 | 265 | 266 | 267 | 268 | --------------------------------------------------------------------------------