20 KiB
Cthulhu Remote Controller (D-Bus Interface)
✅ STABLE: This D-Bus interface has been successfully ported from Orca v49.alpha and integrated into Cthulhu. The API is functional and ready for use, providing external control and automation capabilities for the Cthulhu screen reader.
[TOC]
Overview
Cthulhu exposes a D-Bus service at:
- Service Name:
org.stormux.Cthulhu.Service
- Main Object Path:
/org/stormux/Cthulhu/Service
- Module Object Paths:
/org/stormux/Cthulhu/Service/ModuleName
(e.g.,/org/stormux/Cthulhu/Service/SpeechAndVerbosityManager
)
Dependencies
The D-Bus interface requires:
- dasbus - Python D-Bus library used by Cthulhu for the remote controller implementation. (Installation instructions)
- python-dasbus package (available on most distributions)
Service-Level Commands
Commands available directly on the main service (/org/stormux/Cthulhu/Service
):
Get Cthulhu's Version
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service GetVersion
Alternative using gdbus:
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.GetVersion
Returns: String containing the version (and revision if available)
Example output: s "Cthulhu screen reader version 2025.06.05-plugins (rev 408fb85)"
Present a Custom Message in Speech and/or Braille
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service PresentMessage s "Your message here"
Alternative using gdbus:
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.PresentMessage "Your message here"
Parameters:
message
(string): The message to present to the user
Returns: Boolean indicating success
List Available Service Commands
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service ListCommands
Alternative using gdbus:
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.ListCommands
Returns: List of (command_name, description) tuples
List Registered Modules
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service ListModules
Alternative using gdbus:
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.ListModules
Returns: List of module names
Interacting with Modules
Each registered module exposes its own set of operations. Based on the underlying Cthulhu code, these are categorized as Commands, Runtime Getters, and Runtime Setters:
- Commands: Actions that perform a task. These typically correspond to Cthulhu commands bound
to a keystroke (e.g.,
IncreaseRate
). - Runtime Getters: Operations that retrieve the current value of an item, often a setting
(e.g.,
GetRate
). - Runtime Setters: Operations that set the current value of an item, often a setting
(e.g.,
SetRate
). Note that setting a value does NOT cause it to become permanently saved.
You can discover and execute these for each module.
Discovering Module Capabilities
List Commands for a Module
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/ModuleName \
org.stormux.Cthulhu.Module ListCommands
Alternative using gdbus:
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ListCommands
Replace ModuleName
with an actual module name from ListModules
.
Returns: List of (command_name, description) tuples.
List Runtime Getters for a Module
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/ModuleName \
org.stormux.Cthulhu.Module ListRuntimeGetters
Alternative using gdbus:
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ListRuntimeGetters
Replace ModuleName
with an actual module name from ListModules
.
Returns: List of (getter_name, description) tuples.
List Runtime Setters for a Module
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/ModuleName \
org.stormux.Cthulhu.Module ListRuntimeSetters
Alternative using gdbus:
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ListRuntimeSetters
Replace ModuleName
with an actual module name from ListModules
.
Returns: List of (setter_name, description) tuples.
Executing Module Operations
Execute a Runtime Getter
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/ModuleName \
org.stormux.Cthulhu.Module ExecuteRuntimeGetter s 'PropertyName'
Alternative using gdbus:
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeGetter 'PropertyName'
Parameters:
PropertyName
(string): The name of the runtime getter to execute.
Returns: The value returned by the getter as a GLib variant (type depends on the getter).
Example: Get the current speech rate
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \
org.stormux.Cthulhu.Module ExecuteRuntimeGetter s 'Rate'
This will return the rate as a GLib Variant.
Execute a Runtime Setter
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/ModuleName \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter s 'PropertyName' v <value>
Alternative using gdbus:
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeSetter 'PropertyName' <value>
Parameters:
PropertyName
(string): The name of the runtime setter to execute.<value>
: The value to set, as a GLib variant (type depends on the setter).
Returns: Boolean indicating success.
Example: Set the current speech rate
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter s 'Rate' v '<90>'
Execute a Module Command
# With user notification
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/ModuleName \
org.stormux.Cthulhu.Module ExecuteCommand s 'CommandName' b true
# Without user notification (silent)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/ModuleName \
org.stormux.Cthulhu.Module ExecuteCommand s 'CommandName' b false
Alternative using gdbus:
# With user notification
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteCommand 'CommandName' true
# Without user notification (silent)
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteCommand 'CommandName' false
Parameters (both required):
CommandName
(string): The name of the command to executenotify_user
(boolean): Whether to notify the user of the action (see section below)
Returns: Boolean indicating success
Please Note
Setting notify_user=true
is not a guarantee that feedback will be presented. Some commands
inherently don't make sense to announce. For example:
# This command should simply stop speech, not announce that it is stopping speech.
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \
org.stormux.Cthulhu.Module ExecuteCommand s 'InterruptSpeech' b true
In those cases Cthulhu will ignore the value of notify_user
.
Setting notify_user=false
is a guarantee that Cthulhu will remain silent. If Cthulhu provides any
feedback when notify_user=false
, it should be considered a bug.
Integration with Cthulhu's Plugin System
The D-Bus Remote Controller integrates seamlessly with Cthulhu's pluggy-based plugin system. Plugins can:
- Register their own D-Bus commands using the
@cthulhu_hookimpl
decorator - Expose plugin-specific functionality via the remote controller
- Access the D-Bus service through the dynamic API manager
See the main CLAUDE.md
file for more details on plugin development with D-Bus integration.
Troubleshooting
Service Not Available
If you get "The name is not activatable" or similar errors:
-
Check if Cthulhu is running:
ps aux | grep cthulhu
-
Check if the D-Bus service is registered:
busctl --user list | grep -i cthulhu
-
Verify dasbus is installed:
python3 -c "import dasbus; print('dasbus available')"
-
Check Cthulhu debug output:
DISPLAY=:0 ~/.local/bin/cthulhu --debug 2>&1 | grep -i dbus
Common Issues
- Timing Issues: The D-Bus service starts after ATSPI initialization. Wait a few seconds after Cthulhu startup before attempting D-Bus calls.
- Permissions: Ensure you're using
--user
with busctl/gdbus for session bus access. - Display: Make sure
DISPLAY=:0
is set when running Cthulhu in terminal sessions.
Speech and Key Echo Control Examples
SpeechManager Module
The SpeechManager module provides comprehensive control over Cthulhu's speech settings:
Speech Muting
# Check if speech is muted
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeGetter s "SpeechIsMuted"
# Mute speech
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "SpeechIsMuted" b true
# Unmute speech
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "SpeechIsMuted" b false
Verbosity Control
# Get current verbosity level
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeGetter s "VerbosityLevel"
# Set verbosity to brief
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "VerbosityLevel" s "brief"
# Set verbosity to verbose
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "VerbosityLevel" s "verbose"
Punctuation Control
# Get current punctuation level
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeGetter s "PunctuationLevel"
# Set punctuation level (none/some/most/all)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "PunctuationLevel" s "all"
Other Speech Settings
# Number pronunciation
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "SpeakNumbersAsDigits" b true
# Capitalization style (none/icon/spell)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "CapitalizationStyle" s "spell"
# Indentation and justification speech
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "SpeakIndentationAndJustification" b true
# Display-only text mode
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "OnlySpeakDisplayedText" b false
TypingEchoManager Module
The TypingEchoManager module provides granular control over key echo and typing feedback:
Master Key Echo Control
# Check if key echo is enabled
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeGetter s "KeyEchoEnabled"
# Enable key echo
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "KeyEchoEnabled" b true
# Disable key echo
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "KeyEchoEnabled" b false
Character, Word, and Sentence Echo
# Character echo (echo characters as they're typed)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "CharacterEchoEnabled" b true
# Word echo (speak word when completed)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "WordEchoEnabled" b true
# Sentence echo (speak sentence when completed)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "SentenceEchoEnabled" b false
Key Type Controls
# Alphabetic keys (a-z, A-Z)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "AlphabeticKeysEnabled" b true
# Numeric keys (0-9)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "NumericKeysEnabled" b true
# Punctuation keys (!@#$%^&*(),.;' etc.)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "PunctuationKeysEnabled" b true
# Space key
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "SpaceEnabled" b true
# Modifier keys (Ctrl, Alt, Shift, etc.)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "ModifierKeysEnabled" b false
# Function keys (F1-F12)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "FunctionKeysEnabled" b true
# Action keys (Enter, Tab, Backspace, Delete, Escape)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "ActionKeysEnabled" b true
# Navigation keys (Arrow keys, Home, End, Page Up/Down)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "NavigationKeysEnabled" b false
# Diacritical keys (accented characters)
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "DiacriticalKeysEnabled" b true
Complete Automation Script Example
#!/bin/bash
# Complete Cthulhu Speech and Key Echo Configuration via D-Bus
echo "=== Configuring Cthulhu via D-Bus ==="
# Speech Configuration
echo "Setting up speech preferences..."
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "VerbosityLevel" s "brief"
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "PunctuationLevel" s "some"
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/SpeechManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "SpeakNumbersAsDigits" b true
# Key Echo Configuration
echo "Setting up key echo preferences..."
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "KeyEchoEnabled" b true
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "AlphabeticKeysEnabled" b true
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "NumericKeysEnabled" b true
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/TypingEchoManager \
org.stormux.Cthulhu.Module ExecuteRuntimeSetter sv "ModifierKeysEnabled" b false
echo "Configuration complete!"
Examples
Quick Test Script
#!/bin/bash
# Test Cthulhu D-Bus Remote Controller
echo "Testing Cthulhu D-Bus Remote Controller..."
# Get version
echo "Version:"
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service GetVersion
# Present a message
echo "Presenting message..."
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service PresentMessage s "Hello from D-Bus!"
# List available modules
echo "Available modules:"
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service ListModules
echo "D-Bus test complete!"
Integration Status
- ✅ Core D-Bus service: Fully integrated with Cthulhu
- ✅ Service lifecycle: Automatic start/shutdown with Cthulhu
- ✅ Message presentation:
PresentMessage()
method working - ✅ Version info:
GetVersion()
method working - ✅ Deferred startup: D-Bus service starts after ATSPI initialization to prevent crashes
- ✅ Error handling: Proper exception handling and logging
- 🔄 Module registration: Ready for individual managers to register D-Bus commands
- 🔄 Plugin integration: Plugins can expose D-Bus commands using decorators
Future Development
- Add more speech configuration commands, getters, and setters
- Expose Cthulhu's plugin system commands via D-Bus
- Integrate with Cthulhu's advanced features (indentation audio, self-voicing, etc.)
- Progressively expose all of Cthulhu's commands and settings via the remote controller interface
Related Files
src/cthulhu/dbus_service.py
- Main D-Bus service implementationsrc/cthulhu/cthulhu.py
- Integration and startup logicCLAUDE.md
- Main development guide with plugin integration details