Backport Orca's d-bus remote fixes.

This commit is contained in:
Storm Dragon
2026-04-26 13:18:23 -04:00
parent 337b5d4273
commit 265feb8188
7 changed files with 1017 additions and 888 deletions
+4 -4
View File
@@ -59,8 +59,8 @@ cthulhu
Cthulhu now includes a D-Bus service for remote control: Cthulhu now includes a D-Bus service for remote control:
- **Service**: `org.stormux.Cthulhu.Service` - **Service**: `org.stormux.Cthulhu1.Service`
- **Path**: `/org/stormux/Cthulhu/Service` - **Path**: `/org/stormux/Cthulhu1/Service`
- **Requires**: `dasbus` library (should be installed) - **Requires**: `dasbus` library (should be installed)
### Testing D-Bus Service ### Testing D-Bus Service
@@ -70,10 +70,10 @@ Cthulhu now includes a D-Bus service for remote control:
~/.local/bin/cthulhu ~/.local/bin/cthulhu
# In another terminal, test the service # In another terminal, test the service
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service org.stormux.Cthulhu.Service GetVersion busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service org.stormux.Cthulhu1.Service GetVersion
# Present a message via D-Bus # Present a message via D-Bus
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service org.stormux.Cthulhu.Service PresentMessage s "Hello from D-Bus" busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service org.stormux.Cthulhu1.Service PresentMessage s "Hello from D-Bus"
``` ```
## Development Workflow ## Development Workflow
+89 -174
View File
@@ -22,10 +22,11 @@ on any Linux desktop environment or window manager.
Cthulhu exposes a D-Bus service at: Cthulhu exposes a D-Bus service at:
- **Service Name**: `org.stormux.Cthulhu.Service` - **Service Name**: `org.stormux.Cthulhu1.Service`
- **Main Object Path**: `/org/stormux/Cthulhu/Service` - **Main Object Path**: `/org/stormux/Cthulhu1/Service`
- **Module Object Paths**: `/org/stormux.Cthulhu/Service/ModuleName` - **Module Object Paths**: `/org/stormux/Cthulhu1/Service/ModuleName`
(e.g., `/org/stormux/Cthulhu/Service/SpeechAndVerbosityManager`) (e.g., `/org/stormux/Cthulhu1/Service/SpeechManager`)
- **Module Interfaces**: `org.stormux.Cthulhu1.ModuleName`
See [REMOTE-CONTROLLER-COMMANDS.md](REMOTE-CONTROLLER-COMMANDS.md) for a complete See [REMOTE-CONTROLLER-COMMANDS.md](REMOTE-CONTROLLER-COMMANDS.md) for a complete
list of available commands. list of available commands.
@@ -43,34 +44,34 @@ While this documentation primarily uses `gdbus` for examples, you can use any D-
### Using `busctl` (systemd D-Bus tool) ### Using `busctl` (systemd D-Bus tool)
```bash ```bash
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \ busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu.Service GetVersion org.stormux.Cthulhu1.Service GetVersion
``` ```
### Using Python with `dasbus` ### Using Python with `dasbus`
```python ```python
from dasbus.connection import SessionMessageBus from dasbus.connection import SessionMessageBus
bus = SessionMessageBus() bus = SessionMessageBus()
proxy = bus.get_proxy("org.stormux.Cthulhu.Service", "/org/stormux/Cthulhu/Service") proxy = bus.get_proxy("org.stormux.Cthulhu1.Service", "/org/stormux/Cthulhu1/Service")
version = proxy.GetVersion() version = proxy.GetVersion()
``` ```
### Using `qdbus` (Qt D-Bus tool - available on KDE) ### Using `qdbus` (Qt D-Bus tool - available on KDE)
```bash ```bash
qdbus org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \ qdbus org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu.Service.GetVersion org.stormux.Cthulhu1.Service.GetVersion
``` ```
## Service-Level Commands ## Service-Level Commands
Commands available directly on the main service (`/org/stormux/Cthulhu/Service`): Commands available directly on the main service (`/org/stormux/Cthulhu1/Service`):
### Get Cthulhu's Version ### Get Cthulhu's Version
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service \ --object-path /org/stormux/Cthulhu1/Service \
--method org.stormux.Cthulhu.Service.GetVersion --method org.stormux.Cthulhu1.Service.GetVersion
``` ```
**Returns:** String containing the version (and revision if available) **Returns:** String containing the version (and revision if available)
@@ -78,9 +79,9 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
### Present a Custom Message in Speech and/or Braille ### Present a Custom Message in Speech and/or Braille
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service \ --object-path /org/stormux/Cthulhu1/Service \
--method org.stormux.Cthulhu.Service.PresentMessage "Your message here" --method org.stormux.Cthulhu1.Service.PresentMessage "Your message here"
``` ```
**Parameters:** **Parameters:**
@@ -92,9 +93,9 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
### Show Cthulhu's Preferences GUI ### Show Cthulhu's Preferences GUI
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service \ --object-path /org/stormux/Cthulhu1/Service \
--method org.stormux.Cthulhu.Service.ShowPreferences --method org.stormux.Cthulhu1.Service.ShowPreferences
``` ```
**Returns:** Boolean indicating success **Returns:** Boolean indicating success
@@ -102,44 +103,39 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
### Quit Cthulhu ### Quit Cthulhu
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service \ --object-path /org/stormux/Cthulhu1/Service \
--method org.stormux.Cthulhu.Service.Quit --method org.stormux.Cthulhu1.Service.Quit
``` ```
**Returns:** Boolean indicating if the quit request was accepted **Returns:** Boolean indicating if the quit request was accepted
### List Available Service Commands ## Discovering Modules and Their Capabilities
Use the standard DBus introspection interface to discover registered modules:
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus introspect --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service \ --object-path /org/stormux/Cthulhu1/Service --recurse
--method org.stormux.Cthulhu.Service.ListCommands
``` ```
**Returns:** List of (command_name, description) tuples The child `<node>` entries beneath `/org/stormux/Cthulhu1/Service` are the
registered modules. To inspect the methods and properties for one module:
### List Registered Modules
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus introspect --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service \ --object-path /org/stormux/Cthulhu1/Service/SpeechManager
--method org.stormux.Cthulhu.Service.ListModules
``` ```
**Returns:** List of module names
## Interacting with Modules ## Interacting with Modules
Each registered module exposes its own set of operations. Based on the underlying Cthulhu code, these Each registered module exposes its own native DBus interface. Based on the underlying Cthulhu code,
are categorized as **Commands**, **Runtime Getters**, and **Runtime Setters**: these are categorized as **Commands** and **Properties**:
- **Commands**: Actions that perform a task. These typically correspond to Cthulhu commands bound - **Commands**: Actions that perform a task. These typically correspond to Cthulhu commands bound
to a keystroke (e.g., `IncreaseRate`). to a keystroke (e.g., `IncreaseRate`).
- **Runtime Getters**: Operations that retrieve the current value of an item, often a setting - **Properties**: Runtime values, often settings (e.g., `Rate`). Setting a property does not cause
(e.g., `GetRate`). it to become permanently saved.
- **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. You can discover and execute these for each module.
@@ -147,41 +143,41 @@ You can discover and execute these for each module.
Plugins that expose D-Bus decorators are automatically registered as modules using the naming Plugins that expose D-Bus decorators are automatically registered as modules using the naming
convention `Plugin_<ModuleName>` (e.g., `Plugin_GameMode`, `Plugin_WindowTitleReader`). Use convention `Plugin_<ModuleName>` (e.g., `Plugin_GameMode`, `Plugin_WindowTitleReader`). Use
`ListModules` to discover available plugin modules at runtime. standard DBus introspection to discover available plugin modules at runtime.
#### Plugin_WindowTitleReader #### Plugin_WindowTitleReader
Controls for the Window Title Reader plugin: Controls for the Window Title Reader plugin:
- Parameterized command: `SetEnabled` (`enabled`: bool) - Method: `SetEnabled` (`enabled`: bool, `notify_user`: bool)
- Runtime getter: `Enabled` - Property: `Enabled`
Example: Example:
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \ --object-path /org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
--method org.stormux.Cthulhu.Module.ExecuteParameterizedCommand \ --method org.stormux.Cthulhu1.Plugin_WindowTitleReader.SetEnabled true false
'SetEnabled' '{"enabled": <true>}' false
# Check current state # Check current state
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \ --object-path /org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeGetter 'Enabled' --method org.freedesktop.DBus.Properties.Get \
org.stormux.Cthulhu1.Plugin_WindowTitleReader Enabled
``` ```
Busctl example: Busctl example:
```bash ```bash
busctl --user call org.stormux.Cthulhu.Service \ busctl --user call org.stormux.Cthulhu1.Service \
/org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \ /org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
org.stormux.Cthulhu.Module ExecuteParameterizedCommand \ org.stormux.Cthulhu1.Plugin_WindowTitleReader SetEnabled bb true false
s a{sv} b 'SetEnabled' 1 enabled b true false
# Check current state # Check current state
busctl --user call org.stormux.Cthulhu.Service \ busctl --user call org.stormux.Cthulhu1.Service \
/org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \ /org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
org.stormux.Cthulhu.Module ExecuteRuntimeGetter s 'Enabled' org.freedesktop.DBus.Properties Get ss \
org.stormux.Cthulhu1.Plugin_WindowTitleReader Enabled
``` ```
### PluginSystemManager Module ### PluginSystemManager Module
@@ -190,166 +186,85 @@ The `PluginSystemManager` module provides session-only plugin control:
- `ListPlugins` - `ListPlugins`
- `ListActivePlugins` - `ListActivePlugins`
- `IsPluginActive` (parameterized) - `IsPluginActive`
- `SetPluginActive` (parameterized) - `SetPluginActive`
- `RescanPlugins` - `RescanPlugins`
These calls do **not** persist changes to user preferences. These calls do **not** persist changes to user preferences.
### Discovering Module Capabilities
#### List Commands for a Module
```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 Parameterized Commands for a Module
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ListParameterizedCommands
```
Replace `ModuleName` with an actual module name from `ListModules`.
**Returns:** List of (command_name, description, parameters) tuples, where `parameters` is a
list of (parameter_name, parameter_type) tuples.
**Example output:**
```bash
([('GetVoicesForLanguage',
'Returns a list of available voices for the specified language.',
[('language', 'str'), ('variant', 'str'), ('notify_user', 'bool')])],)
```
#### List Runtime Getters for a Module
```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
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 ### Executing Module Operations
#### Execute a Runtime Getter #### Get a Property
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \ --object-path /org/stormux/Cthulhu1/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeGetter 'PropertyName' --method org.freedesktop.DBus.Properties.Get \
org.stormux.Cthulhu1.ModuleName 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 ##### Example: Get the current speech rate
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \ --object-path /org/stormux/Cthulhu1/Service/SpeechManager \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeGetter 'Rate' --method org.freedesktop.DBus.Properties.Get \
org.stormux.Cthulhu1.SpeechManager Rate
``` ```
This will return the rate as a GLib Variant. #### Set a Property
#### Execute a Runtime Setter
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \ --object-path /org/stormux/Cthulhu1/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeSetter 'PropertyName' <value> --method org.freedesktop.DBus.Properties.Set \
org.stormux.Cthulhu1.ModuleName 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 ##### Example: Set the current speech rate
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \ --object-path /org/stormux/Cthulhu1/Service/SpeechManager \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeSetter 'Rate' '<90>' --method org.freedesktop.DBus.Properties.Set \
org.stormux.Cthulhu1.SpeechManager Rate '<90>'
``` ```
#### Execute a Module Command #### Execute a Module Command
```bash ```bash
# With user notification # With user notification
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \ --object-path /org/stormux/Cthulhu1/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteCommand 'CommandName' true --method org.stormux.Cthulhu1.ModuleName.CommandName true
# Without user notification (silent) # Without user notification (silent)
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \ --object-path /org/stormux/Cthulhu1/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteCommand 'CommandName' false --method org.stormux.Cthulhu1.ModuleName.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) - `notify_user` (boolean): Whether to notify the user of the action (see section below)
**Returns:** Boolean indicating success
#### Execute a Parameterized Command #### Execute a Parameterized Command
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \ --object-path /org/stormux/Cthulhu1/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteParameterizedCommand 'CommandName' \ --method org.stormux.Cthulhu1.ModuleName.CommandName \
'{"param1": <"value1">, "param2": <"value2">}' false "value1" "value2" false
``` ```
**Parameters:** **Parameters:**
- `CommandName` (string): The name of the parameterized command to execute
- `parameters` (dict): Dictionary of parameter names and values as GLib variants
- `notify_user` (boolean): Whether to notify the user of the action - `notify_user` (boolean): Whether to notify the user of the action
**Returns:** The result returned by the command as a GLib variant (type depends on the command)
##### Example: Get voices for a specific language ##### Example: Get voices for a specific language
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \ --object-path /org/stormux/Cthulhu1/Service/SpeechManager \
--method org.stormux.Cthulhu.Module.ExecuteParameterizedCommand 'GetVoicesForLanguage' \ --method org.stormux.Cthulhu1.SpeechManager.GetVoicesForLanguage "en-us" "" false
'{"language": <"en-us">, "variant": <"">}' false
``` ```
This will return a list of available voices for US English. This will return a list of available voices for US English.
@@ -362,9 +277,9 @@ Some commands inherently don't make sense to announce. For example:
```bash ```bash
# This command should simply stop speech, not announce that it is stopping speech. # This command should simply stop speech, not announce that it is stopping speech.
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \ --object-path /org/stormux/Cthulhu1/Service/SpeechManager \
--method org.stormux.Cthulhu.Module.ExecuteCommand 'InterruptSpeech' true --method org.stormux.Cthulhu1.SpeechManager.InterruptSpeech true
``` ```
In those cases Cthulhu will ignore the value of `notify_user`. In those cases Cthulhu will ignore the value of `notify_user`.
+12 -13
View File
@@ -66,22 +66,21 @@ toolkit, OpenOffice/LibreOffice, Gecko, WebKitGtk, and KDE Qt toolkit.
Cthulhu exposes a D-Bus service for external automation and integrations. Cthulhu exposes a D-Bus service for external automation and integrations.
### Service Details ### Service Details
- **Service Name**: `org.stormux.Cthulhu.Service` - **Service Name**: `org.stormux.Cthulhu1.Service`
- **Main Object Path**: `/org/stormux/Cthulhu/Service` - **Main Object Path**: `/org/stormux/Cthulhu1/Service`
- **Module Object Paths**: `/org/stormux/Cthulhu/Service/<ModuleName>` - **Module Object Paths**: `/org/stormux/Cthulhu1/Service/<ModuleName>`
- **Module Interfaces**: `org.stormux.Cthulhu1.<ModuleName>`
### Discovering Capabilities ### Discovering Capabilities
```bash ```bash
# List registered modules # List registered module object paths and introspect their methods/properties
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus introspect --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service \ --object-path /org/stormux/Cthulhu1/Service --recurse
--method org.stormux.Cthulhu.Service.ListModules
# List commands on a module # Inspect one module
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus introspect --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \ --object-path /org/stormux/Cthulhu1/Service/ModuleName
--method org.stormux.Cthulhu.Module.ListCommands
``` ```
### Plugin Modules ### Plugin Modules
@@ -95,8 +94,8 @@ The `PluginSystemManager` module provides **session-only** plugin control (no pr
- `ListPlugins` - `ListPlugins`
- `ListActivePlugins` - `ListActivePlugins`
- `IsPluginActive` (parameterized) - `IsPluginActive`
- `SetPluginActive` (parameterized) - `SetPluginActive`
- `RescanPlugins` - `RescanPlugins`
### Plugin Preferences Pages ### Plugin Preferences Pages
+38 -38
View File
@@ -11,7 +11,7 @@ This document lists the currently available D-Bus commands in Cthulhu's Remote C
## Service-Level Commands ## Service-Level Commands
Available on the main service object `/org/stormux/Cthulhu/Service`: Available on the main service object `/org/stormux/Cthulhu1/Service`:
### Service Commands ### Service Commands
@@ -21,40 +21,37 @@ Available on the main service object `/org/stormux/Cthulhu/Service`:
| `PresentMessage` | Present a message via speech/braille | `message` (string) | Boolean (success) | | `PresentMessage` | Present a message via speech/braille | `message` (string) | Boolean (success) |
| `ShowPreferences` | Opens Cthulhu's preferences GUI | None | Boolean (success) | | `ShowPreferences` | Opens Cthulhu's preferences GUI | None | Boolean (success) |
| `Quit` | Exits Cthulhu | None | Boolean (accepted) | | `Quit` | Exits Cthulhu | None | Boolean (accepted) |
| `ListCommands` | Lists available service commands | None | List of (name, description) tuples |
| `ListModules` | Lists registered D-Bus modules | None | List of module names |
### Example Usage ### Example Usage
```bash ```bash
# Get Cthulhu version # Get Cthulhu version
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \ busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu.Service GetVersion org.stormux.Cthulhu1.Service GetVersion
# Present a custom message # Present a custom message
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \ busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu.Service PresentMessage s "Hello from D-Bus" org.stormux.Cthulhu1.Service PresentMessage s "Hello from D-Bus"
# List available commands
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service ListCommands
# List registered modules
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service ListModules
# Open preferences # Open preferences
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \ busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu.Service ShowPreferences org.stormux.Cthulhu1.Service ShowPreferences
# Quit Cthulhu # Quit Cthulhu
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \ busctl --user call org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service \
org.stormux.Cthulhu.Service Quit org.stormux.Cthulhu1.Service Quit
``` ```
## Module-Level Commands ## Module-Level Commands
Module-level commands are available and can be discovered via `ListModules`. Two key additions are: Module-level commands and properties are discovered with standard DBus introspection:
```bash
gdbus introspect --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu1/Service --recurse
```
Two key additions are:
### PluginSystemManager ### PluginSystemManager
@@ -62,8 +59,8 @@ Session-only plugin control (does not persist preferences):
- `ListPlugins` - `ListPlugins`
- `ListActivePlugins` - `ListActivePlugins`
- `IsPluginActive` (parameterized) - `IsPluginActive`
- `SetPluginActive` (parameterized) - `SetPluginActive`
- `RescanPlugins` - `RescanPlugins`
### Plugin Modules ### Plugin Modules
@@ -73,31 +70,30 @@ convention `Plugin_<ModuleName>` (e.g., `Plugin_GameMode`, `Plugin_WindowTitleRe
#### WindowTitleReader (Plugin_WindowTitleReader) #### WindowTitleReader (Plugin_WindowTitleReader)
- `SetEnabled` (parameterized) -> enabled (bool) - `SetEnabled` -> enabled (bool), notify_user (bool)
- `Enabled` (runtime getter) - `Enabled` (property)
Example: Example:
```bash ```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \ gdbus call --session --dest org.stormux.Cthulhu1.Service \
--object-path /org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \ --object-path /org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
--method org.stormux.Cthulhu.Module.ExecuteParameterizedCommand \ --method org.stormux.Cthulhu1.Plugin_WindowTitleReader.SetEnabled true false
'SetEnabled' '{"enabled": <true>}' false
``` ```
Busctl example: Busctl example:
```bash ```bash
busctl --user call org.stormux.Cthulhu.Service \ busctl --user call org.stormux.Cthulhu1.Service \
/org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \ /org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
org.stormux.Cthulhu.Module ExecuteParameterizedCommand \ org.stormux.Cthulhu1.Plugin_WindowTitleReader SetEnabled bb true false
s a{sv} b 'SetEnabled' 1 enabled b true false
``` ```
# Check current state # Check current state
busctl --user call org.stormux.Cthulhu.Service \ busctl --user call org.stormux.Cthulhu1.Service \
/org/stormux/Cthulhu/Service/Plugin_WindowTitleReader \ /org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader \
org.stormux.Cthulhu.Module ExecuteRuntimeGetter s 'Enabled' org.freedesktop.DBus.Properties Get ss \
org.stormux.Cthulhu1.Plugin_WindowTitleReader Enabled
See [README-REMOTE-CONTROLLER.md](README-REMOTE-CONTROLLER.md) for comprehensive D-Bus API documentation and usage examples. See [README-REMOTE-CONTROLLER.md](README-REMOTE-CONTROLLER.md) for comprehensive D-Bus API documentation and usage examples.
@@ -107,11 +103,15 @@ See [README-REMOTE-CONTROLLER.md](README-REMOTE-CONTROLLER.md) for comprehensive
# Check if Cthulhu's D-Bus service is running # Check if Cthulhu's D-Bus service is running
busctl --user list | grep Cthulhu busctl --user list | grep Cthulhu
# Introspect the service to see all available methods # Introspect the service to see available module nodes
busctl --user introspect org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service busctl --user introspect org.stormux.Cthulhu1.Service /org/stormux/Cthulhu1/Service
# Introspect a module to see its methods and properties
busctl --user introspect org.stormux.Cthulhu1.Service \
/org/stormux/Cthulhu1/Service/Plugin_WindowTitleReader
# Get detailed service information # Get detailed service information
busctl --user status org.stormux.Cthulhu.Service busctl --user status org.stormux.Cthulhu1.Service
``` ```
## Contributing ## Contributing
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -669,14 +669,14 @@ class PluginSystemManager:
logger.error(f"Failed to deregister D-Bus module for plugin {plugin_info.get_module_name()}: {error}") logger.error(f"Failed to deregister D-Bus module for plugin {plugin_info.get_module_name()}: {error}")
@dbus_service.command @dbus_service.command
def list_plugins(self): def list_plugins(self) -> list[str]:
"""Returns a list of available plugin module names.""" """Returns a list of available plugin module names."""
if not self._plugins: if not self._plugins:
self.rescanPlugins() self.rescanPlugins()
return [info.get_module_name() for info in self.plugins] return [info.get_module_name() for info in self.plugins]
@dbus_service.command @dbus_service.command
def list_active_plugins(self): def list_active_plugins(self) -> list[str]:
"""Returns a list of currently active plugin module names.""" """Returns a list of currently active plugin module names."""
return [info.get_module_name() for info in self.plugins if info.loaded] return [info.get_module_name() for info in self.plugins if info.loaded]
@@ -0,0 +1,124 @@
import unittest
from unittest import mock
from cthulhu import dbus_service
class SampleModule:
def __init__(self):
self.enabled = False
self.calls = []
@dbus_service.command
def toggle_feature(self, script=None, event=None, notify_user=True):
"""Toggles the test feature."""
self.calls.append((script, event, notify_user))
return True
@dbus_service.command
def command_without_notify(self, script=None, event=None):
"""Runs a command that does not accept notify_user."""
self.calls.append((script, event))
return True
@dbus_service.command
def list_items(self) -> "list[str]":
"""Returns a list from a command."""
return ["alpha", "beta"]
@dbus_service.parameterized_command
def speak_text(
self,
text: "str",
count: "int" = 1,
script=None,
event=None,
notify_user=True,
) -> "str":
"""Speaks text a number of times."""
self.calls.append((text, count, script, event, notify_user))
return text * count
@dbus_service.getter
def get_enabled(self) -> "bool":
"""Returns whether the feature is enabled."""
return self.enabled
@dbus_service.setter
def set_enabled(self, value: "bool"):
"""Sets whether the feature is enabled."""
self.enabled = value
class NativeInterfaceBuilderTest(unittest.TestCase):
def test_registration_groups_decorated_members_by_native_names(self):
registration = dbus_service._ModuleRegistration.from_module_instance(
"TestModule", SampleModule()
)
self.assertIn("ToggleFeature", registration.get_commands())
self.assertIn("SpeakText", registration.get_parameterized_commands())
self.assertIn("Enabled", registration.get_getters())
self.assertIn("Enabled", registration.get_setters())
self.assertEqual(registration.total_member_count(), 6)
def test_interface_builder_exposes_methods_and_properties(self):
registration = dbus_service._ModuleRegistration.from_module_instance(
"TestModule", SampleModule()
)
interface_class = dbus_service._InterfaceBuilder.build(registration)
self.assertTrue(hasattr(interface_class, "ToggleFeature"))
self.assertTrue(hasattr(interface_class, "CommandWithoutNotify"))
self.assertTrue(hasattr(interface_class, "ListItems"))
self.assertTrue(hasattr(interface_class, "SpeakText"))
self.assertIsInstance(interface_class.Enabled, property)
self.assertFalse(hasattr(interface_class, "ExecuteCommand"))
self.assertIn("org.stormux.Cthulhu1.TestModule", interface_class.__dbus_xml__)
def test_generated_command_method_uses_active_or_default_script(self):
module = SampleModule()
registration = dbus_service._ModuleRegistration.from_module_instance("TestModule", module)
interface = dbus_service._InterfaceBuilder.build(registration)()
script = mock.Mock()
manager = mock.Mock()
manager.get_active_script.return_value = None
manager.get_default_script.return_value = script
event_manager = mock.Mock()
event_manager_module = mock.Mock()
event_manager_module.get_manager.return_value = event_manager
with (
mock.patch.object(dbus_service.script_manager, "get_manager", return_value=manager),
mock.patch.object(
dbus_service, "_get_input_event_manager", return_value=event_manager_module
),
):
self.assertTrue(interface.ToggleFeature(False))
self.assertTrue(interface.CommandWithoutNotify(False))
self.assertEqual(interface.ListItems(False), ["alpha", "beta"])
self.assertEqual(module.calls[0][0], script)
self.assertFalse(module.calls[0][2])
self.assertEqual(module.calls[1][0], script)
self.assertEqual(event_manager.process_remote_controller_event.call_count, 3)
def test_generated_properties_call_getters_and_setters(self):
module = SampleModule()
registration = dbus_service._ModuleRegistration.from_module_instance("TestModule", module)
interface = dbus_service._InterfaceBuilder.build(registration)()
self.assertFalse(interface.Enabled)
interface.Enabled = True
self.assertTrue(module.enabled)
self.assertTrue(interface.Enabled)
class NativeRemoteControllerTest(unittest.TestCase):
def test_controller_uses_versioned_service_name_and_object_path(self):
self.assertEqual(dbus_service.CthulhuRemoteController.SERVICE_NAME, "org.stormux.Cthulhu1.Service")
self.assertEqual(dbus_service.CthulhuRemoteController.OBJECT_PATH, "/org/stormux/Cthulhu1/Service")
if __name__ == "__main__":
unittest.main()