# 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](https://dasbus.readthedocs.io/en/latest/index.html)) - **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 ```bash busctl --user call org.stormux.Cthulhu.Service \ /org/stormux/Cthulhu/Service \ org.stormux.Cthulhu.Service GetVersion ``` **Alternative using gdbus:** ```bash 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 ```bash busctl --user call org.stormux.Cthulhu.Service \ /org/stormux/Cthulhu/Service \ org.stormux.Cthulhu.Service PresentMessage s "Your message here" ``` **Alternative using gdbus:** ```bash 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 ```bash busctl --user call org.stormux.Cthulhu.Service \ /org/stormux/Cthulhu/Service \ org.stormux.Cthulhu.Service ListCommands ``` **Alternative using gdbus:** ```bash 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 ```bash busctl --user call org.stormux.Cthulhu.Service \ /org/stormux/Cthulhu/Service \ org.stormux.Cthulhu.Service ListModules ``` **Alternative using gdbus:** ```bash 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 ```bash busctl --user call org.stormux.Cthulhu.Service \ /org/stormux/Cthulhu/Service/ModuleName \ org.stormux.Cthulhu.Module ListCommands ``` **Alternative using gdbus:** ```bash 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 ```bash busctl --user call org.stormux.Cthulhu.Service \ /org/stormux/Cthulhu/Service/ModuleName \ org.stormux.Cthulhu.Module ListRuntimeGetters ``` **Alternative using gdbus:** ```bash 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 ```bash busctl --user call org.stormux.Cthulhu.Service \ /org/stormux/Cthulhu/Service/ModuleName \ org.stormux.Cthulhu.Module ListRuntimeSetters ``` **Alternative using gdbus:** ```bash 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 ```bash busctl --user call org.stormux.Cthulhu.Service \ /org/stormux/Cthulhu/Service/ModuleName \ org.stormux.Cthulhu.Module ExecuteRuntimeGetter s 'PropertyName' ``` **Alternative using gdbus:** ```bash 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 ```bash 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 ```bash busctl --user call org.stormux.Cthulhu.Service \ /org/stormux/Cthulhu/Service/ModuleName \ org.stormux.Cthulhu.Module ExecuteRuntimeSetter s 'PropertyName' v ``` **Alternative using gdbus:** ```bash gdbus call --session --dest org.stormux.Cthulhu.Service \ --object-path /org/stormux/Cthulhu/Service/ModuleName \ --method org.stormux.Cthulhu.Module.ExecuteRuntimeSetter 'PropertyName' ``` **Parameters:** - `PropertyName` (string): The name of the runtime setter to execute. - ``: The value to set, as a GLib variant (type depends on the setter). **Returns:** Boolean indicating success. ##### Example: Set the current speech rate ```bash 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 ```bash # 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:** ```bash # 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 execute - `notify_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: ```bash # 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: 1. **Check if Cthulhu is running:** ```bash ps aux | grep cthulhu ``` 2. **Check if the D-Bus service is registered:** ```bash busctl --user list | grep -i cthulhu ``` 3. **Verify dasbus is installed:** ```bash python3 -c "import dasbus; print('dasbus available')" ``` 4. **Check Cthulhu debug output:** ```bash 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. ## Examples ### Quick Test Script ```bash #!/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 implementation - `src/cthulhu/cthulhu.py` - Integration and startup logic - `CLAUDE.md` - Main development guide with plugin integration details