More d-bus stuff added.

This commit is contained in:
Storm Dragon
2025-12-09 09:09:42 -05:00
parent 10d94792ed
commit 11240bfcbc
15 changed files with 1000 additions and 22657 deletions
+13
View File
@@ -50,8 +50,21 @@ src/cthulhu/cthulhu_platform.py
# Python bytecode
*.pyc
*.pyo
__pycache__/
# Editor backup files
*~
*.bak
*.swp
*.tmp
*.orig
*.rej
# AT-SPI test/debug files
debug*.log
debug*.out
# Local build directory and artifacts
local-build/
debug-*.out
-14
View File
@@ -1,14 +0,0 @@
Cthulhu Authors
Marc Mulcahy
Willie Walker
Mike Pedersen
Rich Burridge
Joanmarie Diggs
Eitan Isaacson
Scott Haeger
Cthulhu authors
Storm Dragon
-4
View File
@@ -1,4 +0,0 @@
2009-06-09 Willie Walker <william.walker@sun.com>
As of June 9, 2009, the ChangeLog is auto-generated when releasing.
If you are seeing this, use 'git log' for a detailed list of changes.
-20252
View File
File diff suppressed because it is too large Load Diff
+176 -399
View File
@@ -1,8 +1,15 @@
# 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.
> **⚠️⚠️ WORK IN PROGRESS**: This D-Bus interface is brand new and not yet feature complete.
Low-risk feature additions will continue to be made. The API may be
modified beyond bug fixes in future versions based on feedback from consumers of this support.
Such changes will be documented here.
> **💡 Desktop-Agnostic Design**: Cthulhu's D-Bus Remote Controller is built on standard D-Bus
session bus infrastructure and works across all desktop environments (GNOME, KDE Plasma, XFCE,
i3, Sway, etc.). The D-Bus service uses no desktop-specific dependencies and follows universal
D-Bus conventions, making it suitable for integration with any application or automation tool
on any Linux desktop environment or window manager.
[TOC]
@@ -12,16 +19,42 @@ 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`
- **Module Object Paths**: `/org/stormux.Cthulhu/Service/ModuleName`
(e.g., `/org/stormux/Cthulhu/Service/SpeechAndVerbosityManager`)
See [REMOTE-CONTROLLER-COMMANDS.md](REMOTE-CONTROLLER-COMMANDS.md) for a complete
list of available commands.
## 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)
## Alternative Tools for D-Bus Interaction
While this documentation primarily uses `gdbus` for examples, you can use any D-Bus tool or library:
### Using `busctl` (systemd D-Bus tool)
```bash
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service GetVersion
```
### Using Python with `dasbus`
```python
from dasbus.connection import SessionMessageBus
bus = SessionMessageBus()
proxy = bus.get_proxy("org.stormux.Cthulhu.Service", "/org/stormux/Cthulhu/Service")
version = proxy.GetVersion()
```
### Using `qdbus` (Qt D-Bus tool - available on KDE)
```bash
qdbus org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service.GetVersion
```
## Service-Level Commands
@@ -29,13 +62,6 @@ 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 \
@@ -44,17 +70,8 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
**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 \
@@ -67,15 +84,28 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
**Returns:** Boolean indicating success
### List Available Service Commands
### Show Cthulhu's Preferences GUI
```bash
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service ListCommands
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.ShowPreferences
```
**Alternative using gdbus:**
**Returns:** Boolean indicating success
### Quit Cthulhu
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
--method org.stormux.Cthulhu.Service.Quit
```
**Returns:** Boolean indicating if the quit request was accepted
### List Available Service Commands
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service \
@@ -86,13 +116,6 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
### 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 \
@@ -119,13 +142,6 @@ You can discover and execute these for each module.
#### 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 \
@@ -136,15 +152,29 @@ Replace `ModuleName` with an actual module name from `ListModules`.
**Returns:** List of (command_name, description) tuples.
#### List Runtime Getters for a Module
#### List Parameterized Commands for a Module
```bash
busctl --user call org.stormux.Cthulhu.Service \
/org/stormux/Cthulhu/Service/ModuleName \
org.stormux.Cthulhu.Module ListRuntimeGetters
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ListParameterizedCommands
```
**Alternative using gdbus:**
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 \
@@ -157,13 +187,6 @@ Replace `ModuleName` with an actual module name from `ListModules`.
#### 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 \
@@ -178,13 +201,6 @@ Replace `ModuleName` with an actual module name from `ListModules`.
#### 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 \
@@ -200,22 +216,16 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
##### 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'
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeGetter '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 <value>
```
**Alternative using gdbus:**
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
@@ -232,26 +242,13 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
##### 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>'
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \
--method org.stormux.Cthulhu.Module.ExecuteRuntimeSetter 'Rate' '<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 \
@@ -271,325 +268,105 @@ gdbus call --session --dest org.stormux.Cthulhu.Service \
**Returns:** Boolean indicating success
### Please Note
#### Execute a Parameterized Command
**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
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/ModuleName \
--method org.stormux.Cthulhu.Module.ExecuteParameterizedCommand 'CommandName' \
'{"param1": <"value1">, "param2": <"value2">}' false
```
**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
**Returns:** The result returned by the command as a GLib variant (type depends on the command)
##### Example: Get voices for a specific language
```bash
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \
--method org.stormux.Cthulhu.Module.ExecuteParameterizedCommand 'GetVoicesForLanguage' \
'{"language": <"en-us">, "variant": <"">}' false
```
This will return a list of available voices for US English.
### User Notification Applicability
**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
gdbus call --session --dest org.stormux.Cthulhu.Service \
--object-path /org/stormux/Cthulhu/Service/SpeechAndVerbosityManager \
--method org.stormux.Cthulhu.Module.ExecuteCommand 'InterruptSpeech' 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.
## Speech and Key Echo Control Examples
### SpeechManager Module
The SpeechManager module provides comprehensive control over Cthulhu's speech settings:
#### Speech Muting
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
# 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
```bash
#!/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
```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
**Setting `notify_user=false` is not a guarantee that Cthulhu will remain silent**, though for the
most part Cthulhu will try to respect this value. The exceptions are:
1. If executing the command has resulted in UI being shown, such as a dialog or menu, the
newly-shown UI will be presented in speech and/or braille based on the user's settings.
Failure to announce that the user has been removed from one window and placed in another
could be extremely confusing.
2. If the *sole* purpose of the command is to announce something without making any other
changes, e.g. `PresentTime`, executing it with `notify_user=false` makes no sense. Adding
checks and early returns to handle this possibility does not seem worth doing. If you
don't want Cthulhu to present the time, don't ask Cthulhu to present the time. 😃
### Navigator Module "Enabled" State Applicability
**In the Remote Controller, Navigator commands are expected to work even when not "enabled."**
Some of Cthulhu's Navigator modules, namely Table Navigator, Caret Navigator, and Structural Navigator,
have an "enabled" state. The reason for this is very much tied to the keyboard-centric nature of
Cthulhu's commands. For instance, if Cthulhu always grabbed "H" (for heading navigation) and the arrow
keys (for caret navigation), normal interaction with applications would be completely broken. For
this reason, Navigator modules whose commands will prevent normal, native interaction with
applications are typically not enabled by default and can be easily disabled.
In contrast, performing Navigator commands via D-Bus does not prevent native interaction with
applications. For instance, one could use the Remote Controller to move to the next heading without
causing H to stop functioning in editable fields. For this reason, and to avoid a performance hit,
the decision was made to not check if (keyboard-centric) navigation commands were enabled. As a
result, it should be possible to use Remote Controller navigation even in "focus mode" or other
cases where Cthulhu is not controlling the caret. This is by design.
Given the keyboard-centric nature of Cthulhu's commands, there may be instances in which one uses the
Remote Controller for navigation and Cthulhu fails to correctly update its location in response. If
Cthulhu correctly updates its location when the same navigation command is executed via keyboard,
please report the Remote Controller failure as a new bug in Cthulhu's issue tracker.
### The "Stickiness" (or Lack Thereof) of On-The-Fly Settings Changes
Cthulhu has a number of keyboard commands to temporarily change settings such as speech rate, pitch,
volume; capitalization style; punctuation level; etc., etc. The question is: how long should
on-the-fly modifications to settings persist?
Early on in Cthulhu's development, the conclusion was that on-the-fly settings changes should be
seen as quite temporary, presumed to be used to address a specific one-time need. For instance,
if reading some difficult-to-understand text, one might want to reduce the speed just for that text.
If one were doing a final proofread of some content, one might want to briefly set the punctuation
level to all. If one needs slow speed and/or verbose punctuation all the time, those should be set
in Cthulhu's Preferences dialogs -- either globally or on a per-app basis. Cthulhu also has a profile
feature through which the user can save settings and quickly load/unload them by switching profiles*.
Whether or not that historical decision was the right decision goes beyond the scope of the
Remote Controller. The primary purpose of the Remote Controller is to provide D-Bus access to
commands and runtime settings as if they were performed by the user via keyboard command. Thus if
a setting changed via Remote Controller persists (or fails to persist) in the same way as when
changed via keyboard command, it is not a Remote Controller bug. (It may be a general Cthulhu
bug or feature request, and you are encouraged to file it as such.) On the other hand, if the
behavior of the Remote Controller differs from that of the corresponding or related keyboard
command, please report that Remote Controller failure as a new bug in Cthulhu's issue tracker.
\* *Note: Remote Controller support for profile management is still pending.*
+91
View File
@@ -0,0 +1,91 @@
# Cthulhu Remote Controller - Available Commands
This document lists the currently available D-Bus commands in Cthulhu's Remote Controller interface.
> **Note**: This is a work-in-progress. As more modules are exposed via D-Bus, this document will be expanded. Eventually this will be auto-generated using `tools/generate_dbus_documentation.py`.
## Service-Level Commands
Available on the main service object `/org/stormux/Cthulhu/Service`:
### Service Commands
| Command | Description | Parameters | Returns |
|---------|-------------|------------|---------|
| `GetVersion` | Returns Cthulhu's version string | None | String (version + revision) |
| `PresentMessage` | Present a message via speech/braille | `message` (string) | Boolean (success) |
| `ShowPreferences` | Opens Cthulhu's preferences GUI | None | Boolean (success) |
| `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
```bash
# Get Cthulhu version
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service GetVersion
# Present a custom message
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.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
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service ShowPreferences
# Quit Cthulhu
busctl --user call org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service \
org.stormux.Cthulhu.Service Quit
```
## Module-Level Commands
Currently, no additional modules are exposed via D-Bus beyond the base service commands.
**Planned modules** (to be implemented):
- `SpeechAndVerbosityManager` - Speech settings control (muting, verbosity, punctuation, etc.)
- `TypingEchoManager` - Typing echo settings (character/word/sentence echo)
- `DefaultScript` - Core Cthulhu commands
- Additional navigation and presenter modules
See [README-REMOTE-CONTROLLER.md](README-REMOTE-CONTROLLER.md) for comprehensive D-Bus API documentation and usage examples.
## Verifying D-Bus Service Status
```bash
# Check if Cthulhu's D-Bus service is running
busctl --user list | grep Cthulhu
# Introspect the service to see all available methods
busctl --user introspect org.stormux.Cthulhu.Service /org/stormux/Cthulhu/Service
# Get detailed service information
busctl --user status org.stormux.Cthulhu.Service
```
## Contributing
To add new D-Bus-accessible functionality:
1. Add `@dbus_service.command`, `@dbus_service.getter`, or `@dbus_service.setter` decorators to methods
2. Register the module with the D-Bus service in `src/cthulhu/cthulhu.py`
3. Rebuild and test with busctl
4. Update this documentation (or regenerate using `tools/generate_dbus_documentation.py` when available)
## Desktop Environment Compatibility
Cthulhu's D-Bus Remote Controller is desktop-agnostic and works across all Linux desktop environments:
- GNOME, KDE Plasma, XFCE, LXDE
- Tiling window managers (i3, Sway, bspwm, etc.)
- Any environment with D-Bus session bus support
The service uses only standard D-Bus infrastructure with no desktop-specific dependencies.
-104
View File
@@ -1,104 +0,0 @@
dnl a macro to check for ability to create python extensions
dnl AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE])
dnl function also defines PYTHON_INCLUDES
AC_DEFUN([AM_CHECK_PYTHON_HEADERS],
[AC_REQUIRE([AM_PATH_PYTHON])
AC_MSG_CHECKING(for headers required to compile python extensions)
dnl deduce PYTHON_INCLUDES
py_prefix=`$PYTHON -c "import sys; print sys.prefix"`
py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"`
PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}"
if test "$py_prefix" != "$py_exec_prefix"; then
PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}"
fi
AC_SUBST(PYTHON_INCLUDES)
dnl check if the headers exist:
save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES"
AC_TRY_CPP([#include <Python.h>],dnl
[AC_MSG_RESULT(found)
$1],dnl
[AC_MSG_RESULT(not found)
$2])
CPPFLAGS="$save_CPPFLAGS"
])
dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]])
dnl Check if a module containing a given symbol is visible to python.
AC_DEFUN([AM_CHECK_PYMOD],
[AC_REQUIRE([AM_PATH_PYTHON])
py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1)
AC_CACHE_VAL(py_cv_mod_$py_mod_var, [
ifelse([$2],[], [prog="
import sys
try:
from gi.repository import GObject
import $1
except ImportError:
sys.exit(1)
except:
sys.exit(0)
sys.exit(0)"], [prog="
import $1
import $1.$2"])
if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC
then
eval "py_cv_mod_$py_mod_var=yes"
else
eval "py_cv_mod_$py_mod_var=no"
fi
])
py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"`
if test "x$py_val" != xno; then
AC_MSG_RESULT(yes)
ifelse([$3], [],, [$3
])dnl
else
AC_MSG_RESULT(no)
ifelse([$4], [],, [$4
])dnl
fi
])
dnl PYDOC_CHECK()
AC_DEFUN([PYDOC_CHECK],
[
dnl enable/disable documentation building
AC_ARG_ENABLE(pydoc,
AC_HELP_STRING([--enable-pydoc],
[use pydoc to build documentation [default=no]]),,
enable_pydoc=no)
have_pydoc=no
if test x$enable_pydoc = xyes; then
AC_CHECK_FILE("$prefix/bin/pydoc", PYDOC="$prefix/bin/pydoc")
fi
if test -z "$PYDOC"; then
enable_pydoc=no
fi
AM_CONDITIONAL(ENABLE_PYDOC, test x$enable_pydoc = xyes)
])
dnl
dnl JH_ADD_CFLAG(FLAG)
dnl checks whether the C compiler supports the given flag, and if so, adds
dnl it to $CFLAGS. If the flag is already present in the list, then the
dnl check is not performed.
AC_DEFUN([JH_ADD_CFLAG],
[
case " $CFLAGS " in
*@<:@\ \ @:>@$1@<:@\ \ @:>@*)
;;
*)
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_MSG_CHECKING([whether [$]CC understands $1])
AC_TRY_COMPILE([], [], [jh_has_option=yes], [jh_has_option=no])
AC_MSG_RESULT($jh_has_option)
if test $jh_has_option = no; then
CFLAGS="$save_CFLAGS"
fi
;;
esac])
+1 -2
View File
@@ -8,9 +8,8 @@ url="https://git.stormux.org/storm/cthulhu"
arch=(any)
license=(LGPL)
depends=(
# Core AT-SPI accessibility
# Core AT-SPI accessibility
at-spi2-core
python-atspi
gobject-introspection-runtime
python-gobject
python-cairo
-652
View File
@@ -1,652 +0,0 @@
# Makefile.in generated by automake 1.18.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2025 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
am__rm_f = rm -f $(am__rm_f_notfound)
am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = docs
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/build-to-host.m4 \
$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/host-cpu-c-abi.m4 \
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/nls.m4 \
$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
install-exec-recursive install-html-recursive \
install-info-recursive install-pdf-recursive \
install-ps-recursive install-recursive installcheck-recursive \
installdirs-recursive pdf-recursive ps-recursive \
tags-recursive uninstall-recursive
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
$(RECURSIVE_TARGETS) \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
distdir distdir-am
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ATKBRIDGE_CFLAGS = @ATKBRIDGE_CFLAGS@
ATKBRIDGE_LIBS = @ATKBRIDGE_LIBS@
ATSPI2_CFLAGS = @ATSPI2_CFLAGS@
ATSPI2_LIBS = @ATSPI2_LIBS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DESIRED_LINGUAS = @DESIRED_LINGUAS@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
GSTREAMER_LIBS = @GSTREAMER_LIBS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
LDFLAGS = @LDFLAGS@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBPEAS_CFLAGS = @LIBPEAS_CFLAGS@
LIBPEAS_LIBS = @LIBPEAS_LIBS@
LIBS = @LIBS@
LOUIS_TABLE_DIR = @LOUIS_TABLE_DIR@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGMERGE = @MSGMERGE@
MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLATFORM_PATH = @PLATFORM_PATH@
POSUB = @POSUB@
PYGOBJECT_CFLAGS = @PYGOBJECT_CFLAGS@
PYGOBJECT_LIBS = @PYGOBJECT_LIBS@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
REVISION = @REVISION@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
XGETTEXT = @XGETTEXT@
XGETTEXT_015 = @XGETTEXT_015@
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localedir_c = @localedir_c@
localedir_c_make = @localedir_c_make@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = man
all: all-recursive
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu docs/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
# (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
@fail=; \
if $(am__make_keepgoing); then \
failcom='fail=yes'; \
else \
failcom='exit 1'; \
fi; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-recursive
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-recursive
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-recursive
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
$(am__make_dryrun) \
|| test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-recursive
all-am: Makefile
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-$(am__rm_f) $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic mostlyclean-am
distclean: distclean-recursive
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am:
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-man:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am:
.MAKE: $(am__recursive_targets) install-am install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
check-am clean clean-generic cscopelist-am ctags ctags-am \
distclean distclean-generic distclean-tags distdir dvi dvi-am \
html html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs installdirs-am maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
pdf-am ps ps-am tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
# Tell GNU make to disable its built-in pattern rules.
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%
-554
View File
@@ -1,554 +0,0 @@
# Makefile.in generated by automake 1.18.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2025 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
am__rm_f = rm -f $(am__rm_f_notfound)
am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = docs/man
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/build-to-host.m4 \
$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/host-cpu-c-abi.m4 \
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/nls.m4 \
$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
{ test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \
}
man1dir = $(mandir)/man1
am__installdirs = "$(DESTDIR)$(man1dir)"
NROFF = nroff
MANS = $(man1_MANS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ATKBRIDGE_CFLAGS = @ATKBRIDGE_CFLAGS@
ATKBRIDGE_LIBS = @ATKBRIDGE_LIBS@
ATSPI2_CFLAGS = @ATSPI2_CFLAGS@
ATSPI2_LIBS = @ATSPI2_LIBS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DESIRED_LINGUAS = @DESIRED_LINGUAS@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
GSTREAMER_LIBS = @GSTREAMER_LIBS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
LDFLAGS = @LDFLAGS@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBPEAS_CFLAGS = @LIBPEAS_CFLAGS@
LIBPEAS_LIBS = @LIBPEAS_LIBS@
LIBS = @LIBS@
LOUIS_TABLE_DIR = @LOUIS_TABLE_DIR@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGMERGE = @MSGMERGE@
MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLATFORM_PATH = @PLATFORM_PATH@
POSUB = @POSUB@
PYGOBJECT_CFLAGS = @PYGOBJECT_CFLAGS@
PYGOBJECT_LIBS = @PYGOBJECT_LIBS@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
REVISION = @REVISION@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
XGETTEXT = @XGETTEXT@
XGETTEXT_015 = @XGETTEXT_015@
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localedir_c = @localedir_c@
localedir_c_make = @localedir_c_make@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
man1_MANS = cthulhu.1
EXTRA_DIST = \
$(man1_MANS)
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu docs/man/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu docs/man/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-man1: $(man1_MANS)
@$(NORMAL_INSTALL)
@list1='$(man1_MANS)'; \
list2=''; \
test -n "$(man1dir)" \
&& test -n "`echo $$list1$$list2`" \
|| exit 0; \
echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
{ for i in $$list1; do echo "$$i"; done; \
if test -n "$$list2"; then \
for i in $$list2; do echo "$$i"; done \
| sed -n '/\.1[a-z]*$$/p'; \
fi; \
} | while read p; do \
if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; echo "$$p"; \
done | \
sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
sed 'N;N;s,\n, ,g' | { \
list=; while read file base inst; do \
if test "$$base" = "$$inst"; then list="$$list $$file"; else \
echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
$(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
fi; \
done; \
for i in $$list; do echo "$$i"; done | $(am__base_list) | \
while read files; do \
test -z "$$files" || { \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
done; }
uninstall-man1:
@$(NORMAL_UNINSTALL)
@list='$(man1_MANS)'; test -n "$(man1dir)" || exit 0; \
files=`{ for i in $$list; do echo "$$i"; done; \
} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
-e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
tags TAGS:
ctags CTAGS:
cscope cscopelist:
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(MANS)
installdirs:
for dir in "$(DESTDIR)$(man1dir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-$(am__rm_f) $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-man
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man: install-man1
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-man
uninstall-man: uninstall-man1
.MAKE: install-am install-strip
.PHONY: all all-am check check-am clean clean-generic cscopelist-am \
ctags-am distclean distclean-generic distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-man1 install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
pdf-am ps ps-am tags-am uninstall uninstall-am uninstall-man \
uninstall-man1
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
# Tell GNU make to disable its built-in pattern rules.
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%
+1 -1
View File
@@ -13,7 +13,7 @@ if not python3.language_version().version_compare(f'>= @python_minimum_version@'
endif
# Hard dependencies (checked via pkg-config)
dependency('atspi-2', version: '>= 2.48.0')
dependency('atspi-2', version: '>= 2.52.0')
dependency('atk-bridge-2.0', version: '>= 2.26.0')
dependency('pygobject-3.0', version: '>= 3.18')
-652
View File
@@ -1,652 +0,0 @@
# Makefile.in generated by automake 1.18.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2025 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
am__rm_f = rm -f $(am__rm_f_notfound)
am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = src
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/build-to-host.m4 \
$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/host-cpu-c-abi.m4 \
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/nls.m4 \
$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
$(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
install-exec-recursive install-html-recursive \
install-info-recursive install-pdf-recursive \
install-ps-recursive install-recursive installcheck-recursive \
installdirs-recursive pdf-recursive ps-recursive \
tags-recursive uninstall-recursive
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
am__recursive_targets = \
$(RECURSIVE_TARGETS) \
$(RECURSIVE_CLEAN_TARGETS) \
$(am__extra_recursive_targets)
AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
distdir distdir-am
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
DIST_SUBDIRS = $(SUBDIRS)
am__DIST_COMMON = $(srcdir)/Makefile.in
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
sed_first='s,^\([^/]*\)/.*$$,\1,'; \
sed_rest='s,^[^/]*/*,,'; \
sed_last='s,^.*/\([^/]*\)$$,\1,'; \
sed_butlast='s,/*[^/]*$$,,'; \
while test -n "$$dir1"; do \
first=`echo "$$dir1" | sed -e "$$sed_first"`; \
if test "$$first" != "."; then \
if test "$$first" = ".."; then \
dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
else \
first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
if test "$$first2" = "$$first"; then \
dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
else \
dir2="../$$dir2"; \
fi; \
dir0="$$dir0"/"$$first"; \
fi; \
fi; \
dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
done; \
reldir="$$dir2"
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
ATKBRIDGE_CFLAGS = @ATKBRIDGE_CFLAGS@
ATKBRIDGE_LIBS = @ATKBRIDGE_LIBS@
ATSPI2_CFLAGS = @ATSPI2_CFLAGS@
ATSPI2_LIBS = @ATSPI2_LIBS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DESIRED_LINGUAS = @DESIRED_LINGUAS@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
GMSGFMT = @GMSGFMT@
GMSGFMT_015 = @GMSGFMT_015@
GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
GSTREAMER_LIBS = @GSTREAMER_LIBS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTLLIBS = @INTLLIBS@
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
LDFLAGS = @LDFLAGS@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBPEAS_CFLAGS = @LIBPEAS_CFLAGS@
LIBPEAS_LIBS = @LIBPEAS_LIBS@
LIBS = @LIBS@
LOUIS_TABLE_DIR = @LOUIS_TABLE_DIR@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
MSGFMT = @MSGFMT@
MSGMERGE = @MSGMERGE@
MSGMERGE_FOR_MSGFMT_OPTION = @MSGMERGE_FOR_MSGFMT_OPTION@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
PLATFORM_PATH = @PLATFORM_PATH@
POSUB = @POSUB@
PYGOBJECT_CFLAGS = @PYGOBJECT_CFLAGS@
PYGOBJECT_LIBS = @PYGOBJECT_LIBS@
PYTHON = @PYTHON@
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
PYTHON_PLATFORM = @PYTHON_PLATFORM@
PYTHON_PREFIX = @PYTHON_PREFIX@
PYTHON_VERSION = @PYTHON_VERSION@
REVISION = @REVISION@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
XGETTEXT = @XGETTEXT@
XGETTEXT_015 = @XGETTEXT_015@
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localedir_c = @localedir_c@
localedir_c_make = @localedir_c_make@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
pkgpyexecdir = @pkgpyexecdir@
pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
pyexecdir = @pyexecdir@
pythondir = @pythondir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
SUBDIRS = cthulhu
all: all-recursive
.SUFFIXES:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu src/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
# This directory's subdirectories are mostly independent; you can cd
# into them and run 'make' without going through this Makefile.
# To change the values of 'make' variables: instead of editing Makefiles,
# (1) if the variable is set in 'config.status', edit 'config.status'
# (which will cause the Makefiles to be regenerated when you run 'make');
# (2) otherwise, pass the desired values on the 'make' command line.
$(am__recursive_targets):
@fail=; \
if $(am__make_keepgoing); then \
failcom='fail=yes'; \
else \
failcom='exit 1'; \
fi; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
case "$@" in \
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
*) list='$(SUBDIRS)' ;; \
esac; \
for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| eval $$failcom; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-recursive
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
include_option=--etags-include; \
empty_fix=.; \
else \
include_option=--include; \
empty_fix=; \
fi; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test ! -f $$subdir/TAGS || \
set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
fi; \
done; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-recursive
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-recursive
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
@list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
$(am__make_dryrun) \
|| test -d "$(distdir)/$$subdir" \
|| $(MKDIR_P) "$(distdir)/$$subdir" \
|| exit 1; \
dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
$(am__relativize); \
new_distdir=$$reldir; \
dir1=$$subdir; dir2="$(top_distdir)"; \
$(am__relativize); \
new_top_distdir=$$reldir; \
echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
($(am__cd) $$subdir && \
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$$new_top_distdir" \
distdir="$$new_distdir" \
am__remove_distdir=: \
am__skip_length_check=: \
am__skip_mode_fix=: \
distdir) \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-recursive
all-am: Makefile
installdirs: installdirs-recursive
installdirs-am:
install: install-recursive
install-exec: install-exec-recursive
install-data: install-data-recursive
uninstall: uninstall-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-recursive
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-$(am__rm_f) $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-recursive
clean-am: clean-generic mostlyclean-am
distclean: distclean-recursive
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-recursive
dvi-am:
html: html-recursive
html-am:
info: info-recursive
info-am:
install-data-am:
install-dvi: install-dvi-recursive
install-dvi-am:
install-exec-am:
install-html: install-html-recursive
install-html-am:
install-info: install-info-recursive
install-info-am:
install-man:
install-pdf: install-pdf-recursive
install-pdf-am:
install-ps: install-ps-recursive
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-recursive
mostlyclean-am: mostlyclean-generic
pdf: pdf-recursive
pdf-am:
ps: ps-recursive
ps-am:
uninstall-am:
.MAKE: $(am__recursive_targets) install-am install-strip
.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
check-am clean clean-generic cscopelist-am ctags ctags-am \
distclean distclean-generic distclean-tags distdir dvi dvi-am \
html html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs installdirs-am maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
pdf-am ps ps-am tags tags-am uninstall uninstall-am
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
# Tell GNU make to disable its built-in pattern rules.
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%
+6 -3
View File
@@ -20,6 +20,10 @@ import tempfile
import threading
from mimetypes import MimeTypes
import gi
gi.require_version('Atspi', '2.0')
from gi.repository import Atspi
from cthulhu.plugin import Plugin, cthulhu_hookimpl
from cthulhu import debug
from cthulhu import settings_manager
@@ -805,10 +809,9 @@ class OCRDesktop(Plugin):
# Hide window before clicking
self._results_window.hide()
# Perform click using AT-SPI
import pyatspi
# Perform click using AT-SPI2
time.sleep(0.5) # Brief delay
pyatspi.Registry.generateMouseEvent(x_coord, y_coord, "b1c")
Atspi.generate_mouse_event(x_coord, y_coord, "b1c")
debug.printMessage(debug.LEVEL_INFO, f"OCRDesktop: Clicked at ({x_coord}, {y_coord})", True)
+711 -20
View File
@@ -52,6 +52,13 @@ class SpeechAndVerbosityManager:
self._handlers = self._setup_handlers()
self._bindings = self._setup_bindings()
# Register with D-Bus
msg = "SPEECH AND VERBOSITY MANAGER: Registering D-Bus commands."
debug.printMessage(debug.LEVEL_INFO, msg, True)
controller = dbus_service.get_remote_controller()
if controller:
controller.register_decorated_module("SpeechAndVerbosityManager", self)
def get_bindings(self):
"""Returns the notification-presenter keybindings."""
@@ -259,7 +266,186 @@ class SpeechAndVerbosityManager:
def _get_server(self):
return speech.getSpeechServer()
# D-Bus getters and setters for speech settings
# ========================================================================
# D-Bus Speech Server Controls
# ========================================================================
@dbus_service.getter
def get_current_server(self) -> str:
"""Returns the name of the current speech server (Speech Dispatcher or Spiel)."""
server = self._get_server()
if server is None:
return ""
return server.getFactoryName() if hasattr(server, 'getFactoryName') else ""
@dbus_service.getter
def get_available_servers(self) -> list:
"""Returns a list of available speech servers."""
# TODO: Implement multi-server support if needed
return ["speechdispatcher"]
@dbus_service.getter
def get_current_synthesizer(self) -> str:
"""Returns the current synthesizer of the speech server."""
server = self._get_server()
if server is None:
return ""
return server.getOutputModule() if hasattr(server, 'getOutputModule') else ""
@dbus_service.setter
def set_current_synthesizer(self, value: str) -> bool:
"""Sets the current synthesizer of the active speech server."""
server = self._get_server()
if server is None:
return False
try:
if hasattr(server, 'setOutputModule'):
server.setOutputModule(value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting synthesizer: {e}", True)
return False
@dbus_service.getter
def get_available_synthesizers(self) -> list:
"""Returns a list of available synthesizers of the speech server."""
server = self._get_server()
if server is None:
return []
try:
if hasattr(server, 'list_output_modules'):
return server.list_output_modules()
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error getting synthesizers: {e}", True)
return []
# ========================================================================
# D-Bus Voice Controls
# ========================================================================
@dbus_service.getter
def get_available_voices(self) -> list:
"""Returns a list of available voices for the current synthesizer."""
server = self._get_server()
if server is None:
return []
try:
if hasattr(server, 'getVoiceFamilies'):
voices = server.getVoiceFamilies()
return [v.get('name', '') for v in voices if v.get('name')]
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error getting voices: {e}", True)
return []
@dbus_service.getter
def get_current_voice(self) -> str:
"""Returns the current voice name."""
server = self._get_server()
if server is None:
return ""
try:
if hasattr(server, 'getVoiceFamily'):
family = server.getVoiceFamily()
if family:
return family.get('name', '')
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error getting current voice: {e}", True)
return ""
@dbus_service.setter
def set_current_voice(self, voice_name: str) -> bool:
"""Sets the current voice for the active synthesizer."""
server = self._get_server()
if server is None:
return False
try:
if hasattr(server, 'getVoiceFamilies') and hasattr(server, 'setVoiceFamily'):
voices = server.getVoiceFamilies()
for voice_family in voices:
if voice_family.get('name') == voice_name:
server.setVoiceFamily(voice_family)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting voice: {e}", True)
return False
# ========================================================================
# D-Bus Rate/Pitch/Volume Controls
# ========================================================================
@dbus_service.getter
def get_rate(self) -> int:
"""Returns the current speech rate."""
from . import acss
result = 50
default_voice = settings.voices.get(settings.DEFAULT_VOICE)
if default_voice and acss.ACSS.RATE in default_voice:
result = default_voice[acss.ACSS.RATE]
return result
@dbus_service.setter
def set_rate(self, value: int) -> bool:
"""Sets the current speech rate (0-100, default: 50)."""
try:
from . import acss
default_voice = settings.voices.get(settings.DEFAULT_VOICE)
if default_voice and acss.ACSS.RATE in default_voice:
default_voice[acss.ACSS.RATE] = value
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting rate: {e}", True)
return False
@dbus_service.getter
def get_pitch(self) -> float:
"""Returns the current speech pitch."""
from . import acss
result = 5.0
default_voice = settings.voices.get(settings.DEFAULT_VOICE)
if default_voice and acss.ACSS.AVERAGE_PITCH in default_voice:
result = default_voice[acss.ACSS.AVERAGE_PITCH]
return result
@dbus_service.setter
def set_pitch(self, value: float) -> bool:
"""Sets the current speech pitch (0.0-10.0, default: 5.0)."""
try:
from . import acss
default_voice = settings.voices.get(settings.DEFAULT_VOICE)
if default_voice and acss.ACSS.AVERAGE_PITCH in default_voice:
default_voice[acss.ACSS.AVERAGE_PITCH] = value
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting pitch: {e}", True)
return False
@dbus_service.getter
def get_volume(self) -> float:
"""Returns the current speech volume."""
from . import acss
result = 10.0
default_voice = settings.voices.get(settings.DEFAULT_VOICE)
if default_voice and acss.ACSS.GAIN in default_voice:
result = default_voice[acss.ACSS.GAIN]
return result
@dbus_service.setter
def set_volume(self, value: float) -> bool:
"""Sets the current speech volume (0.0-10.0, default: 10.0)."""
try:
from . import acss
default_voice = settings.voices.get(settings.DEFAULT_VOICE)
if default_voice and acss.ACSS.GAIN in default_voice:
default_voice[acss.ACSS.GAIN] = value
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting volume: {e}", True)
return False
# ========================================================================
# D-Bus Speech Enable/Mute Controls
# ========================================================================
@dbus_service.getter
def get_speech_is_muted(self) -> bool:
"""Returns whether speech output is temporarily muted."""
@@ -405,12 +591,484 @@ class SpeechAndVerbosityManager:
_settings_manager.setSetting('capitalizationStyle', settings.CAPITALIZATION_STYLE_SPELL)
else:
return False
self.update_capitalization_style()
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting capitalization style: {e}", True)
return False
def decrease_rate(self, script, event=None):
# ========================================================================
# D-Bus Verbosity Settings
# ========================================================================
@dbus_service.getter
def get_speak_misspelled_indicator(self) -> bool:
"""Returns whether the misspelled indicator is spoken."""
return _settings_manager.getSetting('speakMisspelledIndicator')
@dbus_service.setter
def set_speak_misspelled_indicator(self, value: bool) -> bool:
"""Sets whether the misspelled indicator is spoken."""
try:
_settings_manager.setSetting('speakMisspelledIndicator', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting speak misspelled indicator: {e}", True)
return False
@dbus_service.getter
def get_speak_description(self) -> bool:
"""Returns whether object descriptions are spoken."""
return _settings_manager.getSetting('speakDescription')
@dbus_service.setter
def set_speak_description(self, value: bool) -> bool:
"""Sets whether object descriptions are spoken."""
try:
_settings_manager.setSetting('speakDescription', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting speak description: {e}", True)
return False
@dbus_service.getter
def get_speak_position_in_set(self) -> bool:
"""Returns whether the position and set size of objects are spoken."""
return _settings_manager.getSetting('enablePositionSpeaking')
@dbus_service.setter
def set_speak_position_in_set(self, value: bool) -> bool:
"""Sets whether the position and set size of objects are spoken."""
try:
_settings_manager.setSetting('enablePositionSpeaking', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting speak position in set: {e}", True)
return False
@dbus_service.getter
def get_speak_widget_mnemonic(self) -> bool:
"""Returns whether widget mnemonics are spoken."""
return _settings_manager.getSetting('enableMnemonicSpeaking')
@dbus_service.setter
def set_speak_widget_mnemonic(self, value: bool) -> bool:
"""Sets whether widget mnemonics are spoken."""
try:
_settings_manager.setSetting('enableMnemonicSpeaking', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting speak widget mnemonic: {e}", True)
return False
@dbus_service.getter
def get_speak_tutorial_messages(self) -> bool:
"""Returns whether tutorial messages are spoken."""
return _settings_manager.getSetting('enableTutorialMessages')
@dbus_service.setter
def set_speak_tutorial_messages(self, value: bool) -> bool:
"""Sets whether tutorial messages are spoken."""
try:
_settings_manager.setSetting('enableTutorialMessages', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting speak tutorial messages: {e}", True)
return False
@dbus_service.getter
def get_insert_pauses_between_utterances(self) -> bool:
"""Returns whether pauses are inserted between utterances, e.g. between name and role."""
return _settings_manager.getSetting('enablePauseBreaks')
@dbus_service.setter
def set_insert_pauses_between_utterances(self, value: bool) -> bool:
"""Sets whether pauses are inserted between utterances, e.g. between name and role."""
try:
_settings_manager.setSetting('enablePauseBreaks', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting insert pauses: {e}", True)
return False
@dbus_service.getter
def get_repeated_character_limit(self) -> int:
"""Returns the count at which repeated, non-alphanumeric symbols will be described."""
return _settings_manager.getSetting('repeatCharacterLimit')
@dbus_service.setter
def set_repeated_character_limit(self, value: int) -> bool:
"""Sets the count at which repeated, non-alphanumeric symbols will be described."""
try:
_settings_manager.setSetting('repeatCharacterLimit', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting repeated character limit: {e}", True)
return False
@dbus_service.getter
def get_use_pronunciation_dictionary(self) -> bool:
"""Returns whether the user's pronunciation dictionary should be applied."""
return _settings_manager.getSetting('usePronunciationDictionary')
@dbus_service.setter
def set_use_pronunciation_dictionary(self, value: bool) -> bool:
"""Sets whether the user's pronunciation dictionary should be applied."""
try:
_settings_manager.setSetting('usePronunciationDictionary', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting use pronunciation dictionary: {e}", True)
return False
@dbus_service.getter
def get_messages_are_detailed(self) -> bool:
"""Returns whether informative messages will be detailed or brief."""
return _settings_manager.getSetting('messagesAreDetailed')
@dbus_service.setter
def set_messages_are_detailed(self, value: bool) -> bool:
"""Sets whether informative messages will be detailed or brief."""
try:
_settings_manager.setSetting('messagesAreDetailed', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting messages are detailed: {e}", True)
return False
@dbus_service.getter
def get_speak_indentation_only_if_changed(self) -> bool:
"""Returns whether indentation will be announced only if it has changed."""
return _settings_manager.getSetting('speakIndentationOnlyIfChanged')
@dbus_service.setter
def set_speak_indentation_only_if_changed(self, value: bool) -> bool:
"""Sets whether indentation will be announced only if it has changed."""
try:
_settings_manager.setSetting('speakIndentationOnlyIfChanged', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting speak indentation only if changed: {e}", True)
return False
# ========================================================================
# D-Bus Table Reading Settings
# ========================================================================
@dbus_service.getter
def get_speak_blank_lines(self) -> bool:
"""Returns whether blank lines will be spoken."""
return _settings_manager.getSetting('speakBlankLines')
@dbus_service.setter
def set_speak_blank_lines(self, value: bool) -> bool:
"""Sets whether blank lines will be spoken."""
try:
_settings_manager.setSetting('speakBlankLines', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting speak blank lines: {e}", True)
return False
@dbus_service.getter
def get_speak_row_in_gui_table(self) -> bool:
"""Returns whether Up/Down in GUI tables speaks the row or just the cell."""
return _settings_manager.getSetting('readFullRowInGUITable')
@dbus_service.setter
def set_speak_row_in_gui_table(self, value: bool) -> bool:
"""Sets whether Up/Down in GUI tables speaks the row or just the cell."""
try:
_settings_manager.setSetting('readFullRowInGUITable', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting speak row in GUI table: {e}", True)
return False
@dbus_service.getter
def get_speak_row_in_document_table(self) -> bool:
"""Returns whether Up/Down in text-document tables speaks the row or just the cell."""
return _settings_manager.getSetting('readFullRowInDocumentTable')
@dbus_service.setter
def set_speak_row_in_document_table(self, value: bool) -> bool:
"""Sets whether Up/Down in text-document tables speaks the row or just the cell."""
try:
_settings_manager.setSetting('readFullRowInDocumentTable', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting speak row in document table: {e}", True)
return False
@dbus_service.getter
def get_speak_row_in_spreadsheet(self) -> bool:
"""Returns whether Up/Down in spreadsheets speaks the row or just the cell."""
return _settings_manager.getSetting('readFullRowInSpreadSheet')
@dbus_service.setter
def set_speak_row_in_spreadsheet(self, value: bool) -> bool:
"""Sets whether Up/Down in spreadsheets speaks the row or just the cell."""
try:
_settings_manager.setSetting('readFullRowInSpreadSheet', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting speak row in spreadsheet: {e}", True)
return False
@dbus_service.getter
def get_announce_cell_span(self) -> bool:
"""Returns whether cell spans are announced when greater than 1."""
return _settings_manager.getSetting('speakCellSpan')
@dbus_service.setter
def set_announce_cell_span(self, value: bool) -> bool:
"""Sets whether cell spans are announced when greater than 1."""
try:
_settings_manager.setSetting('speakCellSpan', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting announce cell span: {e}", True)
return False
@dbus_service.getter
def get_announce_cell_coordinates(self) -> bool:
"""Returns whether (non-spreadsheet) cell coordinates are announced."""
return _settings_manager.getSetting('speakCellCoordinates')
@dbus_service.setter
def set_announce_cell_coordinates(self, value: bool) -> bool:
"""Sets whether (non-spreadsheet) cell coordinates are announced."""
try:
_settings_manager.setSetting('speakCellCoordinates', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting announce cell coordinates: {e}", True)
return False
@dbus_service.getter
def get_announce_spreadsheet_cell_coordinates(self) -> bool:
"""Returns whether spreadsheet cell coordinates are announced."""
return _settings_manager.getSetting('speakSpreadsheetCoordinates')
@dbus_service.setter
def set_announce_spreadsheet_cell_coordinates(self, value: bool) -> bool:
"""Sets whether spreadsheet cell coordinates are announced."""
try:
_settings_manager.setSetting('speakSpreadsheetCoordinates', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting announce spreadsheet cell coordinates: {e}", True)
return False
@dbus_service.getter
def get_always_announce_selected_range_in_spreadsheet(self) -> bool:
"""Returns whether the selected range in spreadsheets is always announced."""
return _settings_manager.getSetting('alwaysSpeakSelectedSpreadsheetRange')
@dbus_service.setter
def set_always_announce_selected_range_in_spreadsheet(self, value: bool) -> bool:
"""Sets whether the selected range in spreadsheets is always announced."""
try:
_settings_manager.setSetting('alwaysSpeakSelectedSpreadsheetRange', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting always announce selected range: {e}", True)
return False
@dbus_service.getter
def get_announce_cell_headers(self) -> bool:
"""Returns whether cell headers are announced."""
return _settings_manager.getSetting('speakCellHeaders')
@dbus_service.setter
def set_announce_cell_headers(self, value: bool) -> bool:
"""Sets whether cell headers are announced."""
try:
_settings_manager.setSetting('speakCellHeaders', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting announce cell headers: {e}", True)
return False
# ========================================================================
# D-Bus Context Announcement Settings
# ========================================================================
@dbus_service.getter
def get_announce_blockquote(self) -> bool:
"""Returns whether blockquotes are announced when entered."""
return _settings_manager.getSetting('speakContextBlockquote')
@dbus_service.setter
def set_announce_blockquote(self, value: bool) -> bool:
"""Sets whether blockquotes are announced when entered."""
try:
_settings_manager.setSetting('speakContextBlockquote', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting announce blockquote: {e}", True)
return False
@dbus_service.getter
def get_announce_form(self) -> bool:
"""Returns whether non-landmark forms are announced when entered."""
return _settings_manager.getSetting('speakContextNonLandmarkForm')
@dbus_service.setter
def set_announce_form(self, value: bool) -> bool:
"""Sets whether non-landmark forms are announced when entered."""
try:
_settings_manager.setSetting('speakContextNonLandmarkForm', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting announce form: {e}", True)
return False
@dbus_service.getter
def get_announce_grouping(self) -> bool:
"""Returns whether groupings are announced when entered."""
return _settings_manager.getSetting('speakContextPanel')
@dbus_service.setter
def set_announce_grouping(self, value: bool) -> bool:
"""Sets whether groupings are announced when entered."""
try:
_settings_manager.setSetting('speakContextPanel', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting announce grouping: {e}", True)
return False
@dbus_service.getter
def get_announce_landmark(self) -> bool:
"""Returns whether landmarks are announced when entered."""
return _settings_manager.getSetting('speakContextLandmark')
@dbus_service.setter
def set_announce_landmark(self, value: bool) -> bool:
"""Sets whether landmarks are announced when entered."""
try:
_settings_manager.setSetting('speakContextLandmark', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting announce landmark: {e}", True)
return False
@dbus_service.getter
def get_announce_list(self) -> bool:
"""Returns whether lists are announced when entered."""
return _settings_manager.getSetting('speakContextList')
@dbus_service.setter
def set_announce_list(self, value: bool) -> bool:
"""Sets whether lists are announced when entered."""
try:
_settings_manager.setSetting('speakContextList', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting announce list: {e}", True)
return False
@dbus_service.getter
def get_announce_table(self) -> bool:
"""Returns whether tables are announced when entered."""
return _settings_manager.getSetting('speakContextTable')
@dbus_service.setter
def set_announce_table(self, value: bool) -> bool:
"""Sets whether tables are announced when entered."""
try:
_settings_manager.setSetting('speakContextTable', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting announce table: {e}", True)
return False
@dbus_service.getter
def get_use_color_names(self) -> bool:
"""Returns whether colors are announced by name or as RGB values."""
return _settings_manager.getSetting('useColorNames')
@dbus_service.setter
def set_use_color_names(self, value: bool) -> bool:
"""Sets whether colors are announced by name or as RGB values."""
try:
_settings_manager.setSetting('useColorNames', value)
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting use color names: {e}", True)
return False
# ========================================================================
# D-Bus Speech Control Commands
# ========================================================================
@dbus_service.command
def start_speech(self, script=None, event=None) -> bool:
"""Starts the speech server."""
try:
speech.init()
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error starting speech: {e}", True)
return False
@dbus_service.command
def interrupt_speech(self, script=None, event=None) -> bool:
"""Interrupts the speech server."""
try:
server = self._get_server()
if server:
server.stop()
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error interrupting speech: {e}", True)
return False
@dbus_service.command
def shutdown_speech(self, script=None, event=None) -> bool:
"""Shuts down the speech server."""
try:
server = self._get_server()
if server:
server.shutdownActiveServers()
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error shutting down speech: {e}", True)
return False
@dbus_service.command
def refresh_speech(self, script=None, event=None) -> bool:
"""Shuts down and re-initializes speech."""
try:
self.shutdown_speech()
self.start_speech()
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error refreshing speech: {e}", True)
return False
@dbus_service.setter
def set_speech_is_enabled(self, value: bool) -> bool:
"""Sets whether the speech server is enabled. See also is-muted."""
try:
_settings_manager.setSetting('enableSpeech', value)
if value:
self.start_speech()
else:
self.shutdown_speech()
return True
except Exception as e:
debug.printMessage(debug.LEVEL_WARNING, f"Error setting speech enabled: {e}", True)
return False
@dbus_service.getter
def get_speech_is_enabled(self) -> bool:
"""Returns whether the speech server is enabled. See also is-muted."""
return _settings_manager.getSetting('enableSpeech')
@dbus_service.command
def decrease_rate(self, script=None, event=None):
"""Decreases the speech rate"""
server = self._get_server()
@@ -420,9 +1078,12 @@ class SpeechAndVerbosityManager:
return True
server.decreaseSpeechRate()
if script:
script.presentMessage(messages.SPEECH_SLOWER)
return True
def increase_rate(self, script, event=None):
@dbus_service.command
def increase_rate(self, script=None, event=None):
"""Increases the speech rate"""
server = self._get_server()
@@ -432,9 +1093,12 @@ class SpeechAndVerbosityManager:
return True
server.increaseSpeechRate()
if script:
script.presentMessage(messages.SPEECH_FASTER)
return True
def decrease_pitch(self, script, event=None):
@dbus_service.command
def decrease_pitch(self, script=None, event=None):
"""Decreases the speech pitch"""
server = self._get_server()
@@ -444,9 +1108,12 @@ class SpeechAndVerbosityManager:
return True
server.decreaseSpeechPitch()
if script:
script.presentMessage(messages.SPEECH_LOWER)
return True
def increase_pitch(self, script, event=None):
@dbus_service.command
def increase_pitch(self, script=None, event=None):
"""Increase the speech pitch"""
server = self._get_server()
@@ -456,9 +1123,12 @@ class SpeechAndVerbosityManager:
return True
server.increaseSpeechPitch()
if script:
script.presentMessage(messages.SPEECH_HIGHER)
return True
def decrease_volume(self, script, event=None):
@dbus_service.command
def decrease_volume(self, script=None, event=None):
"""Decreases the speech volume"""
server = self._get_server()
@@ -468,9 +1138,12 @@ class SpeechAndVerbosityManager:
return True
server.decreaseSpeechVolume()
if script:
script.presentMessage(messages.SPEECH_SOFTER)
return True
def increase_volume(self, script, event=None):
@dbus_service.command
def increase_volume(self, script=None, event=None):
"""Increases the speech volume"""
server = self._get_server()
@@ -480,6 +1153,8 @@ class SpeechAndVerbosityManager:
return True
server.increaseSpeechVolume()
if script:
script.presentMessage(messages.SPEECH_LOUDER)
return True
def update_capitalization_style(self):
@@ -506,7 +1181,8 @@ class SpeechAndVerbosityManager:
server.updatePunctuationLevel()
return True
def cycle_synthesizer(self, script, event=None):
@dbus_service.command
def cycle_synthesizer(self, script=None, event=None):
"""Cycle through the speech-dispatcher's available output modules."""
server = self._get_server()
@@ -532,10 +1208,12 @@ class SpeechAndVerbosityManager:
index = 0
server.setOutputModule(available[index])
script.presentMessage(available[index])
if script:
script.presentMessage(available[index])
return True
def cycle_capitalization_style(self, script, event=None):
@dbus_service.command
def cycle_capitalization_style(self, script=None, event=None):
"""Cycle through the speech-dispatcher capitalization styles."""
current_style = _settings_manager.getSetting('capitalizationStyle')
@@ -553,11 +1231,13 @@ class SpeechAndVerbosityManager:
brief = messages.CAPITALIZATION_NONE_BRIEF
_settings_manager.setSetting('capitalizationStyle', new_style)
script.presentMessage(full, brief)
if script:
script.presentMessage(full, brief)
self.update_capitalization_style()
return True
def cycle_punctuation_level(self, script, event=None):
@dbus_service.command
def cycle_punctuation_level(self, script=None, event=None):
"""Cycle through the punctuation levels for speech."""
current_level = _settings_manager.getSetting('verbalizePunctuationStyle')
@@ -579,11 +1259,13 @@ class SpeechAndVerbosityManager:
brief = messages.PUNCTUATION_NONE_BRIEF
_settings_manager.setSetting('verbalizePunctuationStyle', new_level)
script.presentMessage(full, brief)
if script:
script.presentMessage(full, brief)
self.update_punctuation_level()
return True
def cycle_key_echo(self, script, event=None):
@dbus_service.command
def cycle_key_echo(self, script=None, event=None):
"""Cycle through the key echo levels."""
(new_key, new_word, new_sentence) = (False, False, False)
key = _settings_manager.getSetting('enableKeyEcho')
@@ -618,10 +1300,12 @@ class SpeechAndVerbosityManager:
_settings_manager.setSetting('enableKeyEcho', new_key)
_settings_manager.setSetting('enableEchoByWord', new_word)
_settings_manager.setSetting('enableEchoBySentence', new_sentence)
script.presentMessage(full, brief)
if script:
script.presentMessage(full, brief)
return True
def change_number_style(self, script, event=None):
@dbus_service.command
def change_number_style(self, script=None, event=None):
"""Changes spoken number style between digits and words."""
speak_digits = _settings_manager.getSetting('speakNumbersAsDigits')
@@ -633,7 +1317,8 @@ class SpeechAndVerbosityManager:
full = messages.NUMBER_STYLE_DIGITS_FULL
_settings_manager.setSetting('speakNumbersAsDigits', not speak_digits)
script.presentMessage(full, brief)
if script:
script.presentMessage(full, brief)
return True
@dbus_service.command
@@ -666,7 +1351,8 @@ class SpeechAndVerbosityManager:
_settings_manager.setSetting('speechVerbosityLevel', settings.VERBOSITY_LEVEL_BRIEF)
return True
def toggle_indentation_and_justification(self, script, event=None):
@dbus_service.command
def toggle_indentation_and_justification(self, script=None, event=None):
"""Toggles the speaking of indentation and justification."""
value = _settings_manager.getSetting('enableSpeechIndentation')
@@ -677,12 +1363,17 @@ class SpeechAndVerbosityManager:
else:
full = messages.INDENTATION_JUSTIFICATION_OFF_FULL
brief = messages.INDENTATION_JUSTIFICATION_OFF_BRIEF
script.presentMessage(full, brief)
if script:
script.presentMessage(full, brief)
return True
def toggle_table_cell_reading_mode(self, script, event=None):
@dbus_service.command
def toggle_table_cell_reading_mode(self, script=None, event=None):
"""Toggles between speak cell and speak row."""
if not script:
return False
table = script.utilities.getTable(cthulhu_state.locusOfFocus)
if not table:
script.presentMessage(messages.TABLE_NOT_IN_A)
+1
View File
@@ -37,6 +37,7 @@ gi.require_version("Atspi", "2.0")
from gi.repository import Atspi
from . import cmdnames
from . import dbus_service
from . import debug
from . import guilabels
from . import input_event