summaryrefslogtreecommitdiffstats
path: root/platform
diff options
context:
space:
mode:
authorSpartan322 <Megacake1234@gmail.com>2024-11-26 12:56:19 -0500
committerSpartan322 <Megacake1234@gmail.com>2024-11-26 12:56:19 -0500
commite58e18261ea7ed3978146ef8d77a900be2601be3 (patch)
tree79c2a4c34f2d888ff962d76edf474c518d1abdea /platform
parentc5b1645e60a59c0292c04bece3fdb0715a61afea (diff)
parentd09d82d433b03bb3773fd2a8cc8d6ccc2f8739ce (diff)
downloadredot-engine-e58e18261ea7ed3978146ef8d77a900be2601be3.tar.gz
Merge commit godotengine/godot@d09d82d433b03bb3773fd2a8cc8d6ccc2f8739ce
Diffstat (limited to 'platform')
-rw-r--r--platform/android/detect.py19
-rw-r--r--platform/android/export/export_plugin.cpp12
-rw-r--r--platform/web/SCsub11
-rw-r--r--platform/web/api/api.cpp2
-rw-r--r--platform/web/editor/web_tools_editor_plugin.cpp (renamed from platform/web/api/web_tools_editor_plugin.cpp)4
-rw-r--r--platform/web/editor/web_tools_editor_plugin.h (renamed from platform/web/api/web_tools_editor_plugin.h)4
-rw-r--r--platform/web/emscripten_helpers.py7
-rw-r--r--platform/web/export/export_plugin.cpp7
-rw-r--r--platform/web/js/engine/config.js2
-rw-r--r--platform/web/js/engine/engine.js6
-rw-r--r--platform/web/js/libs/library_godot_os.js25
-rw-r--r--platform/web/web_main.cpp8
-rw-r--r--platform/windows/display_server_windows.cpp4
-rw-r--r--platform/windows/os_windows.cpp22
-rw-r--r--platform/windows/tts_windows.cpp10
-rw-r--r--platform/windows/tts_windows.h4
16 files changed, 71 insertions, 76 deletions
diff --git a/platform/android/detect.py b/platform/android/detect.py
index 4bc7e9474b..03a208391c 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -31,6 +31,7 @@ def get_opts():
),
BoolVariable("store_release", "Editor build for Google Play Store (for official builds only)", False),
BoolVariable("generate_apk", "Generate an APK/AAB after building Android library by calling Gradle", False),
+ BoolVariable("swappy", "Use Swappy Frame Pacing library", False),
]
@@ -100,7 +101,7 @@ def detect_swappy():
archs = ["arm64-v8a", "armeabi-v7a", "x86", "x86_64"]
has_swappy = True
for arch in archs:
- if not os.path.isfile("thirdparty/swappy-frame-pacing/" + arch + "/libswappy_static.a"):
+ if not os.path.isfile(f"thirdparty/swappy-frame-pacing/{arch}/libswappy_static.a"):
has_swappy = False
return has_swappy
@@ -176,7 +177,7 @@ def configure(env: "SConsEnvironment"):
env["AS"] = compiler_path + "/clang"
env.Append(
- CCFLAGS=("-fpic -ffunction-sections -funwind-tables -fstack-protector-strong -fvisibility=hidden".split())
+ CCFLAGS=(["-fpic", "-ffunction-sections", "-funwind-tables", "-fstack-protector-strong", "-fvisibility=hidden"])
)
has_swappy = detect_swappy()
@@ -200,28 +201,28 @@ def configure(env: "SConsEnvironment"):
# The NDK adds this if targeting API < 24, so we can drop it when Godot targets it at least
env.Append(CCFLAGS=["-mstackrealign"])
if has_swappy:
- env.Append(LIBPATH=["../../thirdparty/swappy-frame-pacing/x86"])
+ env.Append(LIBPATH=["#thirdparty/swappy-frame-pacing/x86"])
elif env["arch"] == "x86_64":
if has_swappy:
- env.Append(LIBPATH=["../../thirdparty/swappy-frame-pacing/x86_64"])
+ env.Append(LIBPATH=["#thirdparty/swappy-frame-pacing/x86_64"])
elif env["arch"] == "arm32":
- env.Append(CCFLAGS="-march=armv7-a -mfloat-abi=softfp".split())
+ env.Append(CCFLAGS=["-march=armv7-a", "-mfloat-abi=softfp"])
env.Append(CPPDEFINES=["__ARM_ARCH_7__", "__ARM_ARCH_7A__"])
env.Append(CPPDEFINES=["__ARM_NEON__"])
if has_swappy:
- env.Append(LIBPATH=["../../thirdparty/swappy-frame-pacing/armeabi-v7a"])
+ env.Append(LIBPATH=["#thirdparty/swappy-frame-pacing/armeabi-v7a"])
elif env["arch"] == "arm64":
env.Append(CCFLAGS=["-mfix-cortex-a53-835769"])
env.Append(CPPDEFINES=["__ARM_ARCH_8A__"])
if has_swappy:
- env.Append(LIBPATH=["../../thirdparty/swappy-frame-pacing/arm64-v8a"])
+ env.Append(LIBPATH=["#thirdparty/swappy-frame-pacing/arm64-v8a"])
env.Append(CCFLAGS=["-ffp-contract=off"])
# Link flags
- env.Append(LINKFLAGS="-Wl,--gc-sections -Wl,--no-undefined -Wl,-z,now".split())
- env.Append(LINKFLAGS="-Wl,-soname,libgodot_android.so")
+ env.Append(LINKFLAGS=["-Wl,--gc-sections", "-Wl,--no-undefined", "-Wl,-z,now"])
+ env.Append(LINKFLAGS=["-Wl,-soname,libgodot_android.so"])
env.Prepend(CPPPATH=["#platform/android"])
env.Append(CPPDEFINES=["ANDROID_ENABLED", "UNIX_ENABLED"])
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 9bbe299f7d..9f04d22375 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -2531,7 +2531,7 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
// Check for the bin directory.
Ref<DirAccess> da = DirAccess::open(java_sdk_path.path_join("bin"), &errn);
if (errn != OK) {
- err += TTR("Invalid Java SDK path in Editor Settings.");
+ err += TTR("Invalid Java SDK path in Editor Settings.") + " ";
err += TTR("Missing 'bin' directory!");
err += "\n";
valid = false;
@@ -2539,7 +2539,7 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
// Check for the `java` command.
String java_path = get_java_path();
if (!FileAccess::exists(java_path)) {
- err += TTR("Unable to find 'java' command using the Java SDK path.");
+ err += TTR("Unable to find 'java' command using the Java SDK path.") + " ";
err += TTR("Please check the Java SDK directory specified in Editor Settings.");
err += "\n";
valid = false;
@@ -2556,7 +2556,7 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
// Check for the platform-tools directory.
Ref<DirAccess> da = DirAccess::open(sdk_path.path_join("platform-tools"), &errn);
if (errn != OK) {
- err += TTR("Invalid Android SDK path in Editor Settings.");
+ err += TTR("Invalid Android SDK path in Editor Settings.") + " ";
err += TTR("Missing 'platform-tools' directory!");
err += "\n";
valid = false;
@@ -2565,7 +2565,7 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
// Validate that adb is available.
String adb_path = get_adb_path();
if (!FileAccess::exists(adb_path)) {
- err += TTR("Unable to find Android SDK platform-tools' adb command.");
+ err += TTR("Unable to find Android SDK platform-tools' adb command.") + " ";
err += TTR("Please check in the Android SDK directory specified in Editor Settings.");
err += "\n";
valid = false;
@@ -2574,7 +2574,7 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
// Check for the build-tools directory.
Ref<DirAccess> build_tools_da = DirAccess::open(sdk_path.path_join("build-tools"), &errn);
if (errn != OK) {
- err += TTR("Invalid Android SDK path in Editor Settings.");
+ err += TTR("Invalid Android SDK path in Editor Settings.") + " ";
err += TTR("Missing 'build-tools' directory!");
err += "\n";
valid = false;
@@ -2587,7 +2587,7 @@ bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<Edito
// Validate that apksigner is available.
String apksigner_path = get_apksigner_path(target_sdk_version.to_int());
if (!FileAccess::exists(apksigner_path)) {
- err += TTR("Unable to find Android SDK build-tools' apksigner command.");
+ err += TTR("Unable to find Android SDK build-tools' apksigner command.") + " ";
err += TTR("Please check in the Android SDK directory specified in Editor Settings.");
err += "\n";
valid = false;
diff --git a/platform/web/SCsub b/platform/web/SCsub
index 93316ed646..18c8888526 100644
--- a/platform/web/SCsub
+++ b/platform/web/SCsub
@@ -27,9 +27,11 @@ web_files = [
"javascript_bridge_singleton.cpp",
"web_main.cpp",
"os_web.cpp",
- "api/web_tools_editor_plugin.cpp",
]
+if env["target"] == "editor":
+ env.add_source_files(web_files, "editor/*.cpp")
+
sys_env = env.Clone()
sys_env.AddJSLibraries(
[
@@ -59,7 +61,7 @@ for ext in sys_env["JS_EXTERNS"]:
sys_env["ENV"]["EMCC_CLOSURE_ARGS"] += " --externs " + ext.abspath
build = []
-build_targets = ["#bin/redot${PROGSUFFIX}.js", "#bin/redot${PROGSUFFIX}.wasm", "#bin/redot${PROGSUFFIX}.worker.js"]
+build_targets = ["#bin/redot${PROGSUFFIX}.js", "#bin/redot${PROGSUFFIX}.wasm"]
if env["dlink_enabled"]:
# Reset libraries. The main runtime will only link emscripten libraries, not godot ones.
sys_env["LIBS"] = []
@@ -108,6 +110,5 @@ js_wrapped = env.Textfile("#bin/redot", [env.File(f) for f in wrap_list], TEXTFI
# 0 - unwrapped js file (use wrapped one instead)
# 1 - wasm file
-# 2 - worker file
-# 3 - wasm side (when dlink is enabled).
-env.CreateTemplateZip(js_wrapped, build[1], build[2], build[3] if len(build) > 3 else None)
+# 2 - wasm side (when dlink is enabled).
+env.CreateTemplateZip(js_wrapped, build[1], build[2] if len(build) > 2 else None)
diff --git a/platform/web/api/api.cpp b/platform/web/api/api.cpp
index cd7f11e152..5a0334be22 100644
--- a/platform/web/api/api.cpp
+++ b/platform/web/api/api.cpp
@@ -33,14 +33,12 @@
#include "api.h"
#include "javascript_bridge_singleton.h"
-#include "web_tools_editor_plugin.h"
#include "core/config/engine.h"
static JavaScriptBridge *javascript_bridge_singleton;
void register_web_api() {
- WebToolsEditorPlugin::initialize();
GDREGISTER_ABSTRACT_CLASS(JavaScriptObject);
GDREGISTER_ABSTRACT_CLASS(JavaScriptBridge);
javascript_bridge_singleton = memnew(JavaScriptBridge);
diff --git a/platform/web/api/web_tools_editor_plugin.cpp b/platform/web/editor/web_tools_editor_plugin.cpp
index 3986d224c4..4f453f4ad3 100644
--- a/platform/web/api/web_tools_editor_plugin.cpp
+++ b/platform/web/editor/web_tools_editor_plugin.cpp
@@ -32,8 +32,6 @@
#include "web_tools_editor_plugin.h"
-#if defined(TOOLS_ENABLED) && defined(WEB_ENABLED)
-
#include "core/config/engine.h"
#include "core/config/project_settings.h"
#include "core/io/dir_access.h"
@@ -157,5 +155,3 @@ void WebToolsEditorPlugin::_zip_recursive(String p_path, String p_base_path, zip
cur = dir->get_next();
}
}
-
-#endif // TOOLS_ENABLED && WEB_ENABLED
diff --git a/platform/web/api/web_tools_editor_plugin.h b/platform/web/editor/web_tools_editor_plugin.h
index 478d9b86c3..cda24a58da 100644
--- a/platform/web/api/web_tools_editor_plugin.h
+++ b/platform/web/editor/web_tools_editor_plugin.h
@@ -33,8 +33,6 @@
#ifndef WEB_TOOLS_EDITOR_PLUGIN_H
#define WEB_TOOLS_EDITOR_PLUGIN_H
-#if defined(TOOLS_ENABLED) && defined(WEB_ENABLED)
-
#include "core/io/zip_io.h"
#include "editor/plugins/editor_plugin.h"
@@ -59,6 +57,4 @@ public:
static void initialize() {}
};
-#endif // TOOLS_ENABLED && WEB_ENABLED
-
#endif // WEB_TOOLS_EDITOR_PLUGIN_H
diff --git a/platform/web/emscripten_helpers.py b/platform/web/emscripten_helpers.py
index 3122271a71..aca5d4ecba 100644
--- a/platform/web/emscripten_helpers.py
+++ b/platform/web/emscripten_helpers.py
@@ -30,7 +30,7 @@ def create_engine_file(env, target, source, externs, threads_enabled):
return env.Substfile(target=target, source=[env.File(s) for s in source], SUBST_DICT=subst_dict)
-def create_template_zip(env, js, wasm, worker, side):
+def create_template_zip(env, js, wasm, side):
binary_name = "godot.editor" if env.editor_build else "godot"
zip_dir = env.Dir(env.GetTemplateZipPath())
in_files = [
@@ -45,9 +45,6 @@ def create_template_zip(env, js, wasm, worker, side):
zip_dir.File(binary_name + ".audio.worklet.js"),
zip_dir.File(binary_name + ".audio.position.worklet.js"),
]
- if env["threads"]:
- in_files.append(worker)
- out_files.append(zip_dir.File(binary_name + ".worker.js"))
# Dynamic linking (extensions) specific.
if env["dlink_enabled"]:
in_files.append(side) # Side wasm (contains the actual Godot code).
@@ -66,8 +63,6 @@ def create_template_zip(env, js, wasm, worker, side):
"logo.svg",
"favicon.png",
]
- if env["threads"]:
- cache.append("godot.editor.worker.js")
opt_cache = ["godot.editor.wasm"]
subst_dict = {
"___GODOT_VERSION___": get_build_version(False),
diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp
index 145ce0dd2a..3ef2bf3810 100644
--- a/platform/web/export/export_plugin.cpp
+++ b/platform/web/export/export_plugin.cpp
@@ -217,9 +217,6 @@ Error EditorExportPlatformWeb::_add_manifest_icon(const String &p_path, const St
}
Error EditorExportPlatformWeb::_build_pwa(const Ref<EditorExportPreset> &p_preset, const String p_path, const Vector<SharedObject> &p_shared_objects) {
- List<String> preset_features;
- get_preset_features(p_preset, &preset_features);
-
String proj_name = GLOBAL_GET("application/config/name");
if (proj_name.is_empty()) {
proj_name = "Redot Game";
@@ -246,9 +243,6 @@ Error EditorExportPlatformWeb::_build_pwa(const Ref<EditorExportPreset> &p_prese
cache_files.push_back(name + ".apple-touch-icon.png");
}
- if (preset_features.find("threads")) {
- cache_files.push_back(name + ".worker.js");
- }
cache_files.push_back(name + ".audio.worklet.js");
cache_files.push_back(name + ".audio.position.worklet.js");
replaces["___GODOT_CACHE___"] = Variant(cache_files).to_json_string();
@@ -842,7 +836,6 @@ Error EditorExportPlatformWeb::_export_project(const Ref<EditorExportPreset> &p_
DirAccess::remove_file_or_error(basepath + ".html");
DirAccess::remove_file_or_error(basepath + ".offline.html");
DirAccess::remove_file_or_error(basepath + ".js");
- DirAccess::remove_file_or_error(basepath + ".worker.js");
DirAccess::remove_file_or_error(basepath + ".audio.worklet.js");
DirAccess::remove_file_or_error(basepath + ".audio.position.worklet.js");
DirAccess::remove_file_or_error(basepath + ".service.worker.js");
diff --git a/platform/web/js/engine/config.js b/platform/web/js/engine/config.js
index e4aec319c5..1acea70125 100644
--- a/platform/web/js/engine/config.js
+++ b/platform/web/js/engine/config.js
@@ -295,8 +295,6 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused-
'locateFile': function (path) {
if (!path.startsWith('godot.') && !path.startsWith('redot.')) {
return path;
- } else if (path.endsWith('.worker.js')) {
- return `${loadPath}.worker.js`;
} else if (path.endsWith('.audio.worklet.js')) {
return `${loadPath}.audio.worklet.js`;
} else if (path.endsWith('.audio.position.worklet.js')) {
diff --git a/platform/web/js/engine/engine.js b/platform/web/js/engine/engine.js
index 9718c9fd5a..211711b649 100644
--- a/platform/web/js/engine/engine.js
+++ b/platform/web/js/engine/engine.js
@@ -241,7 +241,11 @@ const Engine = (function () {
*/
installServiceWorker: function () {
if (this.config.serviceWorker && 'serviceWorker' in navigator) {
- return navigator.serviceWorker.register(this.config.serviceWorker);
+ try {
+ return navigator.serviceWorker.register(this.config.serviceWorker);
+ } catch (e) {
+ return Promise.reject(e);
+ }
}
return Promise.resolve();
},
diff --git a/platform/web/js/libs/library_godot_os.js b/platform/web/js/libs/library_godot_os.js
index 44617cbadc..6217794fb0 100644
--- a/platform/web/js/libs/library_godot_os.js
+++ b/platform/web/js/libs/library_godot_os.js
@@ -443,8 +443,12 @@ const GodotPWA = {
godot_js_pwa_cb__sig: 'vi',
godot_js_pwa_cb: function (p_update_cb) {
if ('serviceWorker' in navigator) {
- const cb = GodotRuntime.get_func(p_update_cb);
- navigator.serviceWorker.getRegistration().then(GodotPWA.updateState.bind(null, cb));
+ try {
+ const cb = GodotRuntime.get_func(p_update_cb);
+ navigator.serviceWorker.getRegistration().then(GodotPWA.updateState.bind(null, cb));
+ } catch (e) {
+ GodotRuntime.error('Failed to assign PWA callback', e);
+ }
}
},
@@ -452,12 +456,17 @@ const GodotPWA = {
godot_js_pwa_update__sig: 'i',
godot_js_pwa_update: function () {
if ('serviceWorker' in navigator && GodotPWA.hasUpdate) {
- navigator.serviceWorker.getRegistration().then(function (reg) {
- if (!reg || !reg.waiting) {
- return;
- }
- reg.waiting.postMessage('update');
- });
+ try {
+ navigator.serviceWorker.getRegistration().then(function (reg) {
+ if (!reg || !reg.waiting) {
+ return;
+ }
+ reg.waiting.postMessage('update');
+ });
+ } catch (e) {
+ GodotRuntime.error(e);
+ return 1;
+ }
return 0;
}
return 1;
diff --git a/platform/web/web_main.cpp b/platform/web/web_main.cpp
index ac8e11f400..ddcbc40727 100644
--- a/platform/web/web_main.cpp
+++ b/platform/web/web_main.cpp
@@ -40,6 +40,10 @@
#include "scene/main/scene_tree.h"
#include "scene/main/window.h" // SceneTree only forward declares it.
+#ifdef TOOLS_ENABLED
+#include "editor/web_tools_editor_plugin.h"
+#endif
+
#include <emscripten/emscripten.h>
#include <stdlib.h>
@@ -106,6 +110,10 @@ void main_loop_callback() {
extern EMSCRIPTEN_KEEPALIVE int godot_web_main(int argc, char *argv[]) {
os = new OS_Web();
+#ifdef TOOLS_ENABLED
+ WebToolsEditorPlugin::initialize();
+#endif
+
// We must override main when testing is enabled
TEST_MAIN_OVERRIDE
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index a5969de971..8f27889382 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -3246,6 +3246,10 @@ void DisplayServerWindows::process_events() {
}
_THREAD_SAFE_UNLOCK_
+ if (tts) {
+ tts->process_events();
+ }
+
if (!drop_events) {
_process_key_events();
Input::get_singleton()->flush_buffered_events();
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 7ff14cc1e1..dbd68e56ec 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -819,22 +819,10 @@ double OS_Windows::get_unix_time() const {
}
void OS_Windows::delay_usec(uint32_t p_usec) const {
- constexpr uint32_t tolerance = 1000 + 20;
-
- uint64_t t0 = get_ticks_usec();
- uint64_t target_time = t0 + p_usec;
-
- // Calculate sleep duration with a tolerance for fine-tuning.
- if (p_usec > tolerance) {
- uint32_t coarse_sleep_usec = p_usec - tolerance;
- if (coarse_sleep_usec >= 1000) {
- Sleep(coarse_sleep_usec / 1000);
- }
- }
-
- // Spin-wait until we reach the precise target time.
- while (get_ticks_usec() < target_time) {
- YieldProcessor();
+ if (p_usec < 1000) {
+ Sleep(1);
+ } else {
+ Sleep(p_usec / 1000);
}
}
@@ -1753,7 +1741,7 @@ String OS_Windows::get_stdin_string(int64_t p_buffer_size) {
data.resize(p_buffer_size);
DWORD count = 0;
if (ReadFile(GetStdHandle(STD_INPUT_HANDLE), data.ptrw(), data.size(), &count, nullptr)) {
- return String::utf8((const char *)data.ptr(), count);
+ return String::utf8((const char *)data.ptr(), count).replace("\r\n", "\n").rstrip("\n");
}
return String();
diff --git a/platform/windows/tts_windows.cpp b/platform/windows/tts_windows.cpp
index 82704a5d6e..5d16f086b0 100644
--- a/platform/windows/tts_windows.cpp
+++ b/platform/windows/tts_windows.cpp
@@ -45,7 +45,7 @@ void __stdcall TTS_Windows::speech_event_callback(WPARAM wParam, LPARAM lParam)
} else if (event.eEventId == SPEI_END_INPUT_STREAM) {
DisplayServer::get_singleton()->tts_post_utterance_event(DisplayServer::TTS_UTTERANCE_ENDED, tts->ids[stream_num].id);
tts->ids.erase(stream_num);
- tts->_update_tts();
+ tts->update_requested = true;
} else if (event.eEventId == SPEI_WORD_BOUNDARY) {
const Char16String &string = tts->ids[stream_num].string;
int pos = 0;
@@ -62,8 +62,8 @@ void __stdcall TTS_Windows::speech_event_callback(WPARAM wParam, LPARAM lParam)
}
}
-void TTS_Windows::_update_tts() {
- if (!is_speaking() && !paused && queue.size() > 0) {
+void TTS_Windows::process_events() {
+ if (update_requested && !paused && queue.size() > 0 && !is_speaking()) {
DisplayServer::TTSUtterance &message = queue.front()->get();
String text;
@@ -112,6 +112,8 @@ void TTS_Windows::_update_tts() {
ids[(uint32_t)stream_number] = ut;
queue.pop_front();
+
+ update_requested = false;
}
}
@@ -209,7 +211,7 @@ void TTS_Windows::speak(const String &p_text, const String &p_voice, int p_volum
if (is_paused()) {
resume();
} else {
- _update_tts();
+ update_requested = true;
}
}
diff --git a/platform/windows/tts_windows.h b/platform/windows/tts_windows.h
index cf315b988d..c8a879e93a 100644
--- a/platform/windows/tts_windows.h
+++ b/platform/windows/tts_windows.h
@@ -57,9 +57,9 @@ class TTS_Windows {
int id;
};
HashMap<uint32_t, UTData> ids;
+ bool update_requested = false;
static void __stdcall speech_event_callback(WPARAM wParam, LPARAM lParam);
- void _update_tts();
static TTS_Windows *singleton;
@@ -75,6 +75,8 @@ public:
void resume();
void stop();
+ void process_events();
+
TTS_Windows();
~TTS_Windows();
};