Tolk is an application extension (DLL) that allows Windows applications to output text through screen reader software (assistive technology for the blind and visually impaired). It is an abstraction layer on top of the vendor-specific APIs that auto-detects the active screen reader, allowing for clean and simple client code. Speech and braille output are supported in 32-bit and 64-bit environments. See Supported screen readers for more details. In addition to screen readers, Microsoft Speech API (SAPI) is also supported. The name Tolk is a Dutch word meaning interpreter.
There are APIs for the following languages:
- C/C++
- Java
- Microsoft .NET (C# and VB)
- Python
- AutoIt
- PureBasic
Tolk is distributed under the GNU Lesser General Public License version 3 (LGPLv3). Client libraries and headers are distributed under their own license.
The key components of Tolk are the screen reader drivers. They wrap a specific screen reader API into an abstract interface which is then used by Tolk's auto-detection mechanism. SAPI, albeit not a screen reader, also has its own driver. To keep things simple and secure, these screen reader drivers are not exposed to client code. Functions that output text or that silence speech are asynchronous. That is, they return immediately once the appropriate commands have been queued for processing by the active screen reader. All other functions are synchronous. That is, they return only when their work is done. Finally, a few words on multi-threaded applications. Tolk is not thread-safe. Also, some of the screen reader drivers use COM. You have two options for initializing COM:
- Call
Tolk_Loadon every thread that uses Tolk. Match every call by a call toTolk_Unload. Tolk will initialize COM if required. - Initialize and uninitialize COM yourself and call
Tolk_Loadonly once in your application. You still need a matching call toTolk_Unload. This is also what you should do in languages that automatically deal with COM, e.g. .NET.
Tolk has functions for (un)initialization, querying and using the active screen reader, and for working with Microsoft SAPI. To use Tolk, import the appropriate version of Tolk.dll into your application. In C/C++ this is usually done by including Tolk.h and linking with the appropriate import library Tolk.lib. You could also use the Windows API functions LoadLibrary and FreeLibrary. Other languages are also supported, see Wrappers. If you're working in an unsupported language, use its specific facilities to call into the DLL.
The lib directory contains the required screen reader API DLLs. Tolk expects these DLLs to be found either in the current working directory or somewhere in the PATH. If a DLL for a screen reader is not found, that screen reader will be unavailable. Note that some screen readers use COM and therefore don't need API DLLs.
Before using Tolk you need to initialize it with Tolk_Load, and uninitialize it with Tolk_Unload when you are done. You can then use all the other functions.
The most important way to send text to the active screen reader is using Tolk_Output. The first parameter to this function is the Unicode string of text, the second parameter indicates whether or not previously queued speech should be interrupted (or canceled, flushed, etc). In languages that support this feature, the second parameter is optional and defaults to false. The advantage of using Tolk_Output is that it tries both speech and braille. If you need something more specialized, use Tolk_Speak for speech, Tolk_Braille for braille and Tolk_Silence to interrupt previously queued speech. All these functions return true on success and false otherwise, but because of the auto-detection mechanism it is recommended (and safe) to discard this return value and simply insert the required calls wherever you need screen reader output. This keeps your code clean and straight-forward.
There are functions to find out more about the active screen reader driver. You can get the name of the currently active screen reader through Tolk_DetectScreenReader. This returns the name as Unicode string or NULL if none of the supported screen readers is active. As the name implies, this function tries auto-detection if required. Internally, Tolk's other functions use this, so it is not necessary to call this yourself unless you actually need the common name.
If a screen reader is active, you can use Tolk_HasSpeech and Tolk_HasBraille to find out whether the driver supports speech or braille, respectively.
For synchronization, Tolk_IsSpeaking returns whether or not the active screen reader is speaking text at the time of the call, assuming the driver supports this query. Note that not many drivers implement this functionality because of limitations in screen reader APIs. See the Status column of the Supported screen readers table for details. There is no such function for braille, since braille is instantaneous.
Tolk can output text through Microsoft SAPI. This is mostly meant as a fallback mechanism. To do this, Tolk has a screen reader driver that uses SAPI 5.4. Therefore, the functionality is limited to what screen reader drivers provide. Applications that need more control should use SAPI directly. Another consequence is that you can control SAPI usage explicitly via Tolk_TrySAPI() and Tolk_PreferSAPI() functions.
By default, support for SAPI is enabled. To change this, use Tolk_TrySAPI, passing true to enable SAPI or false to disable it. The required driver will automatically be (un)loaded.
SAPI is initially put at the end of the auto-detection chain. This is good for using it as a fallback option when none of the supported screen readers is running. It is also possible to have Tolk prefer SAPI over the other screen reader drivers. This is good for basic SAPI output where screen readers are only tried if SAPI fails or if SAPI 5.4 or later is unavailable. To change the preference for SAPI, use Tolk_PreferSAPI. This also takes a boolean parameter, true to prefer SAPI or false to prefer the traditional screen readers.
The most efficient way of enabling SAPI support is to set it up before calling Tolk_Load. However, you can also call these functions after Tolk has already been loaded. This will trigger the screen reader detection process and is therefore slightly less efficient.
Wrappers around Tolk.dll have been added for some languages to make things easier:
- .NET (C#/VB.NET): Provides managed access to Tolk functions for .NET applications.
- Java: Enables Java applications to call Tolk functionality via JNI.
- Python: Offers a Pythonic interface for screen reader output.
- AutoIt: Allows AutoIt scripts to use Tolk for accessibility.
- PureBasic: Provides native bindings for PureBasic projects.
The wrappers cover all functions and use the language's native types where possible.
Take a look at the examples directory to get started. This directory contains console applications in the supported languages that demonstrate the basic usage. Note that Microsoft SAPI will stop speaking when your application closes, which means that it will not work with these console applications because they return immediately after queueing text. Add a short delay (sleep) to work around this if you want to try SAPI.
The following table lists the supported screen readers in the order in which they are auto-detected. Screen Reader Speech Braille Status x86 x64 ARM64 NVDA Yes Yes No Yes Yes Yes JAWS Yes Yes No Yes Yes No Window-Eyes Yes Yes No Yes Yes No System Access Yes Yes No Yes Yes No SuperNova Yes No No Yes No No ZoomText Yes No Yes Yes Yes No ZDSR Yes Yes Yes Yes Yes No BoyPCReader Yes No Yes Yes Yes No SAPI Yes No Yes Yes Yes Partial*
- All screen readers that do not support ARM64 will run via x64 emulation.
- SuperNova is the only screen reader that does not have a 64-bit compatible API.
- SuperNova has support for braille, but the API does not let you use it.
- SuperNova can speak even if the user turned the voice off, but in that state interrupts will not work.
- Some screen readers (notably Window-Eyes and ZoomText) support many more functions, but there are no plans to implement any of them.
- The driver for Microsoft SAPI explicitly disables XML handling because there is no way to be sure SAPI is being used and other drivers don't support this.
- Window-Eyes is obsolete, but support has not yet been removed.
If you want to compile Tolk yourself, here's what you need to build the whole thing:
- Microsoft Visual C++
- Windows Software Development Kit (SDK)
- Java Development Kit (JDK)
- Microsoft .NET Framework
- Python
- Pandoc
The root directory and
examplesdirectories contain various batch files as a starting point. They assume the required tools are in yourPATHand that the JDK include directory is inINCLUDE. For the examples you will also need to copy over any dependency files.
build.bat # Build both Debug and Release (x86 + x64 + ARM64)
build.bat debug # Build Debug only (x86 + x64 + ARM64)
build.bat release # Build Release only (x86 + x64 + ARM64)dist/
├── x86/
│ ├── Debug/ # 32-bit x86 Debug build (Tolk.dll, drivers, PDB symbols)
│ └── Release/ # 32-bit x86 Release build
├── x64/
│ ├── Debug/ # 64-bit x64 Debug build
│ └── Release/ # 64-bit x64 Release build
├── arm64/
│ ├── Debug/ # ARM64 Debug build (NVDA only)
│ └── Release/ # ARM64 Release build (NVDA only)
├── wrappers/ # Shared language wrappers (all architectures)
│ ├── dotnet/ # .NET wrapper (TolkDotNet.dll)
│ ├── java/ # Java wrapper (Tolk.jar)
│ ├── python/ # Python wrapper (Tolk.py)
│ ├── autoit/ # AutoIt wrapper (Tolk.au3)
│ └── purebasic/ # PureBasic wrapper (Tolk.pb)
├── dotnet/ # Legacy .NET wrapper (backward compatibility)
├── java/ # Legacy Java wrapper (backward compatibility)
├── docs/ # Documentation
├── DEBUG_FEATURES.txt
└── LICENSE files
Tolk includes a unified logging system that helps with debugging and troubleshooting.
| Feature | Debug Build | Release Build |
|---|---|---|
| Optimization | Disabled (/Od) |
Full Optimization (/O2) |
| Debug Symbols | Full PDB | None |
| Runtime Checks | Enabled (RTC1 + RTCsu) | Disabled |
| Log File Output | ✅ Tolk_Debug.log |
❌ None |
| Console Output (ERR/WRN) | ✅ Colored | ❌ None |
| OutputDebugString | ✅ All logs | ✅ All logs |
When using the Debug build, Tolk automatically creates a log file in the calling process working directory:
YourApplication.exe
Tolk.dll (Debug version)
Tolk_Debug.log ← Auto-generated log file
All log entries include a millisecond-precision timestamp:
[2024-06-15 14:30:25.123][Tolk][INF] Tolk.cpp(123): Tolk_Load() called
[2024-06-15 14:30:25.125][Tolk][INF] ScreenReaderDriverNVDA.cpp(45): Loading nvdaControllerClient.dll
[2024-06-15 14:30:25.128][Tolk][ERR] ScreenReaderDriverBOY.cpp(78): Failed to load byctrl.dll
[2024-06-15 14:30:25.130][Tolk][WRN] ScreenReaderDriverZDSR.cpp(56): ZDSR not running
[ERR]- Errors (red in console)[WRN]- Warnings (yellow in console)[INF]- Information[DBG]- Debug details
- Console: Debug builds automatically print
[ERR]and[WRN]messages to the console with color coding - Log File:
Tolk_Debug.logcontains all log entries with timestamps (UTF-8 encoded) - DebugView: All logs are sent to Windows
OutputDebugString- use DebugView to view them in real-time
To completely disable logging at compile time, define TOLK_DISABLE_LOGGING before including TolkDebug.h.
- Davy Kager
- Leonard de Ruijter
- Axel Vugts
- QuentinC, who has developed Universal Speech, another great screen reader library