Skip to content

sapi5: skip over invalid voices rather than causing the entire driver to fail#20430

Open
michaelDCurran wants to merge 5 commits into
betafrom
i20128
Open

sapi5: skip over invalid voices rather than causing the entire driver to fail#20430
michaelDCurran wants to merge 5 commits into
betafrom
i20128

Conversation

@michaelDCurran

Copy link
Copy Markdown
Member

Link to issue number:

Fixes #20128

Summary of the issue:

The sapi5 driver can fail completely at initialization, if there is an invalid voice token found in the registry.
Currently NVDA asks sapi5 to enumerate all voices itself using ISpeechVoice::getVoices, however any invalid voice causes the entire enumeration to fail with a COM error.

Description of user facing changes:

Description of developer facing changes:

Description of development approach:

  • The list of available voice tokens is now generated by manually enumerating the voice keys in the registry, and creating each token from its ID. If one fails to create, it is skipped over.
  • Setting the voice now directly converts an ID into a token, rather than re-fetching all tokens and finding which one has the given voiceID.

Testing strategy:

  • Locally run both sapi5 64 and sapi5 32 synth drivers in NvDA, moving through voices in the synth settings ring.
  • Verify with the issue author that the problem is fixed for their specific case.

Known issues with pull request:

None known.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the SAPI5 (64-bit) synth driver initialization so that malformed/invalid voice tokens no longer cause the entire driver to fail. It does this by enumerating voice token IDs directly from the registry and creating tokens one-by-one, skipping those that fail to instantiate.

Changes:

  • Add registry-based enumeration of SAPI5 voice token IDs and per-token creation/validation.
  • Update _getVoiceTokens to return only successfully created tokens (skipping invalid ones).
  • Update voice selection to create a token directly from the stored voice ID, avoiding a full re-enumeration.

Comment thread source/synthDrivers/sapi5.py
Comment thread source/synthDrivers/sapi5.py
@cary-rowen

Copy link
Copy Markdown
Contributor

Can this be included in the 2026.2?

@michaelDCurran

michaelDCurran commented Jul 1, 2026 via email

Copy link
Copy Markdown
Member Author

Comment thread source/synthDrivers/sapi5.py
Comment thread source/synthDrivers/sapi5.py Outdated
Comment thread source/synthDrivers/sapi5.py Outdated
@seanbudd

seanbudd commented Jul 2, 2026

Copy link
Copy Markdown
Member

should this target beta since #20128 is on the 2026.2 milestone?

michaelDCurran and others added 5 commits July 3, 2026 11:47
…an just calling getVoices, so that invalid voices can be skipped without causing the entire driver to fail. Also setting a voice from an ID creates the token directly, rather than needing to enumerate all tokens.
Co-authored-by: Sean Budd <sean@nvaccess.org>
@michaelDCurran michaelDCurran changed the base branch from master to beta July 3, 2026 01:48
@michaelDCurran

Copy link
Copy Markdown
Member Author

I have rebased this on beta.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NVDA 2026.1 can't load sapi 5 64 bit synthesizer

4 participants