Skip to content

New SRAL_GetTTSEngines and SRAL_GetAssistiveTechEngines bit mask functions#36

Draft
JRJurman wants to merge 2 commits into
m1maker:mainfrom
JRJurman:engine-masks
Draft

New SRAL_GetTTSEngines and SRAL_GetAssistiveTechEngines bit mask functions#36
JRJurman wants to merge 2 commits into
m1maker:mainfrom
JRJurman:engine-masks

Conversation

@JRJurman
Copy link
Copy Markdown
Contributor

@JRJurman JRJurman commented May 14, 2026

Summary

Previously, it was not possible to exclusively route to Assistive Technology engines (Screen Readers, Braille devices) without already knowing the specific engine values. For most games / applications, we'd almost certainly want to default to ALWAYS reading out to those devices, with an in-app option to also read out to the operating system's Text to Speech engine (always reading out to these could be noisy for most non-blind consumers).

This PR introduces two new functions, SRAL_GetTTSEngines and SRAL_GetAssistiveTechEngines, which should make it easier for developers to specifically toggle which engines should be enabled.

Snippet from the README:

bool tts_option_enabled = /* your app's setting */;
SRAL_SetEnginesExclude(tts_option_enabled ? 0 : SRAL_GetTTSEngines());
SRAL_Speak("hello", true);  // routes to AT always; to TTS only if opted in

Note

I'm not especially tied to either of these function names - I'm happy to update these if there are alternatives we think would be better

As part of this change, we also needed to update how the speech_engine_update function chooses an engine, and allow it to be null even if we previously had one selected. These changes are tested in SRALExample.c (see Testing below).

Additionally, there are some small updates throughout (updating the build artifacts, updating the binding files to match latest engine list). If we'd rather those be in a separate PR, I'm happy to split this up. See the PR comments below for more details.

Testing

I validated this via the tests in SRALExample.c. I've added checks that the engine masks are disjoint (they don't contain any overlapping engines). There's also a check that when we exclude all engines that the current engine is properly set as None.

I also updated the macOS example app SRALCocoaExample.m locally, but I hesitated on including those changes here (since I think defaulting to TTS is probably better than having that behind a checkbox). If that would feel valuable, I'm happy to include that as part of this PR.

@JRJurman JRJurman marked this pull request as ready for review May 14, 2026 11:00
Copy link
Copy Markdown
Contributor Author

@JRJurman JRJurman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are the smaller miscellaneous updates that don't have to do with the PR directly, but are still useful to have.


- name: Configure CMake
run: cmake . -B build -DCMAKE_OSX_ARCHITECTURES=x86_64 -DBUILD_SHARED_LIBS=ON
run: cmake . -B build -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DBUILD_SHARED_LIBS=ON
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

noticed that we were missing the Apple Silicone build targets, so including that here as well

Comment thread Bindings/go/SRAL/types.go
AndroidTextToSpeechEngine
// AllEngines is a bitmask of all supported engines.
AllEngines Engine = NVDAEngine | JAWSEngine | ZDSREngine | NarratorEngine | UIAEngine | SAPIEngine | SpeechDispatcherEngine | NSSpeechEngine | VoiceOverEngine | AVSpeechEngine
AllEngines Engine = NVDAEngine | JAWSEngine | ZDSREngine | NarratorEngine | UIAEngine | SAPIEngine | SpeechDispatcherEngine | NSSpeechEngine | VoiceOverEngine | AVSpeechEngine | AndroidAccessibilityManagerEngine | AndroidTextToSpeechEngine
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing engines from the Android PRs 😅

Comment thread Bindings/Python/sral.py
Comment on lines +34 to +35
ANDROID_ACCESSIBILITY_MANAGER = 1 << 11
ANDROID_TEXT_TO_SPEECH = 1 << 12
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above, missing engines from the Android PRs

Comment thread Examples/C/SRALExample.c
}
bool found = false;
for (int engine_val = SRAL_ENGINE_NVDA; engine_val <= SRAL_ENGINE_AV_SPEECH; engine_val <<= 1) {
for (int engine_val = SRAL_ENGINE_NVDA; engine_val <= SRAL_ENGINE_ANDROID_TEXT_TO_SPEECH; engine_val <<= 1) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

throughout this file we reference SRAL_ENGINE_AV_SPEECH as the last engine, so we change it to now be SRAL_ENGINE_ANDROID_TEXT_TO_SPEECH (although in retrospect, we probably should have a dedicated variable that semantically references this as last_engine_value, or something like that)

@m1maker m1maker self-requested a review May 14, 2026 12:10
Comment thread SRC/SRAL.cpp
Comment on lines +637 to +654
extern "C" SRAL_API int SRAL_GetTTSEngines(void) {
return SRAL_ENGINE_SAPI
| SRAL_ENGINE_SPEECH_DISPATCHER
| SRAL_ENGINE_NS_SPEECH
| SRAL_ENGINE_AV_SPEECH
| SRAL_ENGINE_ANDROID_TEXT_TO_SPEECH;
}

extern "C" SRAL_API int SRAL_GetAssistiveTechEngines(void) {
return SRAL_ENGINE_NVDA
| SRAL_ENGINE_JAWS
| SRAL_ENGINE_ZDSR
| SRAL_ENGINE_NARRATOR
| SRAL_ENGINE_UIA
| SRAL_ENGINE_VOICE_OVER
| SRAL_ENGINE_ANDROID_ACCESSIBILITY_MANAGER;
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't hardcode engines here. Instead, consider making engine feature or Sral::Engine interface method with engine category (either TTS or screen reader).

@m1maker m1maker marked this pull request as draft May 15, 2026 17:53
@m1maker
Copy link
Copy Markdown
Owner

m1maker commented May 15, 2026

@JRJurman

I can give you another idea on how to do this:

enum SRAL_EngineCategory {
 SRAL_ENGINE_CATEGORY_UNKNOWN = 0,
 SRAL_ENGINE_CATEGORY_SCREEN_READER,
 SRAL_ENGINE_CATEGORY_TEXT_TO_SPEECH_ENGINE,
 SRAL_ENGINE_CATEGORY_ACCESSIBILITY_PROVIDER
};

Then, for example, create this function

SRAL_API SRAL_EngineCategory SRAL_GetEngineCategory(int engine);

The static function get_engine in SRAL main implementation can help you to map the integer parameter value to the runtime-initialized engine pointer.

Then declare and implement, for example GetCategory method in all Sral::Engine interface implementations.

Then, for example, engines like NVDA, JAWS, VoiceOver etc. will be categorized as screen readers, SAPI, Speech Dispatcher, AV etc. as TTS, UIA and Android AM will be a11y providers.

Sorry for the mess, but I'm not working on this project right now and I won't be for a while. But I don't want to ignore or discard people's contributions. Thank you for that.

@m1maker m1maker added the enhancement New feature or request label May 15, 2026
@JRJurman
Copy link
Copy Markdown
Contributor Author

No worries! I appreciate the ideas and feedback here. I'll probably spend some time either this weekend or later next week working through some options to see which comes out most elegant. But yeah, no need to rush on reviews when that is up, and I appreciate all the reviews and ideas you've given ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants