Updated extensions.
This commit is contained in:
@@ -1 +1,79 @@
|
||||
Placeholder
|
||||
# TTYverse Extensions
|
||||
|
||||
This directory contains bundled extensions for TTYverse, the command-line fediverse client.
|
||||
|
||||
## Extension Loading
|
||||
|
||||
TTYverse uses a simple XDG-compliant extension system. Extensions are only loaded from:
|
||||
|
||||
**`~/.local/share/ttyverse/extensions/`** (XDG_DATA_HOME/ttyverse/extensions)
|
||||
|
||||
Extensions are loaded with the `-exts` flag:
|
||||
```bash
|
||||
perl ttyverse.pl -exts=soundpack
|
||||
perl ttyverse.pl -exts=extension1,extension2
|
||||
```
|
||||
|
||||
## Managing Extensions
|
||||
|
||||
Use the included management script to enable/disable bundled extensions:
|
||||
|
||||
```bash
|
||||
# Show available and enabled extensions
|
||||
./extensions/manage-extensions.sh list
|
||||
|
||||
# Enable an extension (creates symlink in XDG directory)
|
||||
./extensions/manage-extensions.sh enable soundpack
|
||||
|
||||
# Disable an extension (removes from XDG directory)
|
||||
./extensions/manage-extensions.sh disable soundpack
|
||||
|
||||
# Check extension status
|
||||
./extensions/manage-extensions.sh status soundpack
|
||||
```
|
||||
|
||||
## Available Extensions
|
||||
|
||||
### soundpack.pl
|
||||
Plays notification sounds for different types of posts (timeline, replies, DMs, mentions, search results).
|
||||
|
||||
**Configuration options** (add to `~/.config/ttyverse/ttyverse.rc`):
|
||||
```
|
||||
extpref_sound_command=paplay # Sound player (paplay, play, ogg123, etc.)
|
||||
extpref_soundpack=default # Sound pack name
|
||||
```
|
||||
|
||||
**Sound files location**: `~/.local/share/ttyverse/sounds/default/`
|
||||
- `default.ogg` - Regular timeline posts
|
||||
- `mention.ogg` - Mentions of your username
|
||||
- `dm.ogg` - Direct messages
|
||||
- `me.ogg` - Your own posts
|
||||
- `follow.ogg` - New followers
|
||||
- `boost.ogg` - Your posts boosted
|
||||
- `favourite.ogg` - Your posts favourited
|
||||
- `poll.ogg` - Poll notifications
|
||||
- `announcement.ogg` - Server announcements
|
||||
|
||||
## Installing Custom Extensions
|
||||
|
||||
1. Copy your extension `.pl` file to `~/.local/share/ttyverse/extensions/`
|
||||
2. Load it with `-exts=yourextension`
|
||||
|
||||
## Extension Development
|
||||
|
||||
Extensions are Perl modules that hook into TTYverse's event system. Key variables:
|
||||
|
||||
- `$data` - XDG data directory (`~/.local/share/ttyverse`)
|
||||
- `$config` - XDG config directory (`~/.config/ttyverse`)
|
||||
- `$store` - Extension workspace (persistent storage)
|
||||
- `$silent` - Silent mode flag
|
||||
- `$stdout` - Output filehandle
|
||||
|
||||
Extensions can define these functions:
|
||||
- `$notifier` - Called for new posts
|
||||
- `$heartbeat` - Called periodically
|
||||
- `$handle` - Called for user commands
|
||||
- `$prepost` - Called before posting
|
||||
- `$postpost` - Called after posting
|
||||
|
||||
Set `$store->{'loaded'} = 1;` at the end of your extension.
|
||||
@@ -0,0 +1,70 @@
|
||||
# TTYverse Desktop Notifications Extension (libnotify-perl)
|
||||
# Adapted from original TTYtter extension
|
||||
# Provides desktop notifications using GTK Gtk2::Notify
|
||||
# Published under the Floodgap Free Software License: http://www.floodgap.com/software/ffsl/
|
||||
|
||||
# What is it?
|
||||
# This extension enables desktop notifications for TTYverse using the
|
||||
# libnotify system on Linux/Unix with GUI environments.
|
||||
|
||||
# Requirements:
|
||||
# - Gtk2::Notify Perl module
|
||||
# - GUI environment with DISPLAY set
|
||||
# - libnotify system installed
|
||||
|
||||
# Installation:
|
||||
# Install dependency: cpan Gtk2::Notify
|
||||
# Or on Debian/Ubuntu: sudo apt install libgtk2-notify-perl
|
||||
# Or on Fedora/RHEL: sudo dnf install perl-Gtk2-Notify
|
||||
# Or on Arch: sudo pacman -S perl-gtk2-notify
|
||||
|
||||
eval { require Gtk2::Notify };
|
||||
if($@){
|
||||
print "-- TTYverse notification extension requires Gtk2::Notify\n";
|
||||
print "-- Install with: cpan Gtk2::Notify\n";
|
||||
print "-- Or on Debian/Ubuntu: sudo apt install libgtk2-notify-perl\n";
|
||||
print "-- Or on Fedora/RHEL: sudo dnf install perl-Gtk2-Notify\n";
|
||||
print "-- Or on Arch: sudo pacman -S perl-gtk2-notify\n";
|
||||
die();
|
||||
}
|
||||
|
||||
sub notifier_libnotifyperl {
|
||||
# Skip notifications if no GUI display available
|
||||
return 1 if(!$ENV{'DISPLAY'});
|
||||
|
||||
my $class = shift;
|
||||
my $text = shift;
|
||||
my $ref = shift; # Post reference data (unused in this version)
|
||||
|
||||
# Handle initialization
|
||||
if (!defined($class) || !defined($notify_send_path)) {
|
||||
if (!defined($class)) {
|
||||
return 1 if ($script); # Skip in script mode
|
||||
$class = 'TTYverse Desktop Notifications';
|
||||
$text = 'Desktop notifications are now active for TTYverse.';
|
||||
Gtk2::Notify->init('ttyverse');
|
||||
print $streamout "-- $text\n" if (!$silent);
|
||||
}
|
||||
}
|
||||
|
||||
# Show notification if system is properly initialized
|
||||
if (Gtk2::Notify->is_initted()) {
|
||||
my $notification = Gtk2::Notify->new(
|
||||
"TTYverse: $class",
|
||||
$text
|
||||
);
|
||||
|
||||
# Set reasonable timeout (5 seconds)
|
||||
$notification->set_timeout(5_000);
|
||||
|
||||
if($notification->show()) {
|
||||
# Debug output (optional)
|
||||
# print $streamout "-- Notification shown: $class\n" if ($debug);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Make sure the module loads properly
|
||||
1;
|
||||
Executable
+287
@@ -0,0 +1,287 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# TTYverse Extension Manager
|
||||
# Simple XDG-compliant extension management for ~/.local/share/ttyverse/extensions/
|
||||
#
|
||||
|
||||
# XDG data directory for TTYverse
|
||||
DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/ttyverse"
|
||||
EXT_DIR="$DATA_DIR/extensions"
|
||||
BUNDLED_DIR="$(dirname "$0")"
|
||||
|
||||
# Colors for output (only if stdout is a terminal)
|
||||
if [[ -t 1 ]]; then
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
RED='\033[0;31m'
|
||||
NC='\033[0m'
|
||||
else
|
||||
GREEN=''
|
||||
YELLOW=''
|
||||
RED=''
|
||||
NC=''
|
||||
fi
|
||||
|
||||
# Ensure extension directory exists
|
||||
mkdir -p "$EXT_DIR"
|
||||
|
||||
show_help() {
|
||||
cat << EOF
|
||||
TTYverse Extension Manager
|
||||
|
||||
Usage: $0 <command> [extension_name]
|
||||
|
||||
Commands:
|
||||
list Show available and enabled extensions
|
||||
enable <ext> Enable an extension (symlink to XDG extensions directory)
|
||||
disable <ext> Disable an extension (remove from XDG extensions directory)
|
||||
status <ext> Show status of specific extension
|
||||
help Show this help
|
||||
|
||||
Examples:
|
||||
$0 list # Show all extensions
|
||||
$0 enable soundpack # Enable soundpack extension
|
||||
$0 disable soundpack # Disable soundpack extension
|
||||
$0 status soundpack # Check if soundpack is enabled
|
||||
|
||||
XDG Extensions Directory: $EXT_DIR
|
||||
Bundled Extensions: $BUNDLED_DIR
|
||||
|
||||
Note: TTYverse only loads extensions from the XDG directory.
|
||||
Use this script to enable/disable bundled extensions or install your own.
|
||||
EOF
|
||||
}
|
||||
|
||||
list_extensions() {
|
||||
echo -e "${GREEN}Available Extensions:${NC}"
|
||||
for ext in "$BUNDLED_DIR"/*.pl; do
|
||||
if [[ -f "$ext" ]]; then
|
||||
basename="${ext##*/}"
|
||||
name="${basename%.pl}"
|
||||
if [[ -L "$EXT_DIR/$basename" || -f "$EXT_DIR/$basename" ]]; then
|
||||
echo -e " ${GREEN}✓${NC} $name (enabled)"
|
||||
else
|
||||
echo -e " ${YELLOW}○${NC} $name (available)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "\n${GREEN}User Extensions:${NC}"
|
||||
for ext in "$EXT_DIR"/*.pl; do
|
||||
if [[ -f "$ext" && ! -L "$ext" ]]; then
|
||||
basename="${ext##*/}"
|
||||
name="${basename%.pl}"
|
||||
echo -e " ${GREEN}●${NC} $name (user-installed)"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
enable_extension() {
|
||||
local name="$1"
|
||||
local ext_file="$name.pl"
|
||||
local bundled_path="$BUNDLED_DIR/$ext_file"
|
||||
local user_path="$EXT_DIR/$ext_file"
|
||||
|
||||
if [[ ! -f "$bundled_path" ]]; then
|
||||
echo -e "${RED}Error:${NC} Extension '$name' not found in bundled extensions"
|
||||
echo "Available extensions:"
|
||||
for ext in "$BUNDLED_DIR"/*.pl; do
|
||||
if [[ -f "$ext" ]]; then
|
||||
basename="${ext##*/}"
|
||||
echo " ${basename%.pl}"
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [[ -L "$user_path" ]]; then
|
||||
echo -e "${YELLOW}Warning:${NC} Extension '$name' is already enabled"
|
||||
return 0
|
||||
elif [[ -f "$user_path" ]]; then
|
||||
echo -e "${YELLOW}Warning:${NC} User-installed extension '$name' already exists"
|
||||
return 0
|
||||
fi
|
||||
|
||||
ln -s "$(realpath "$bundled_path")" "$user_path"
|
||||
echo -e "${GREEN}✓${NC} Enabled extension: $name"
|
||||
echo " Linked: $bundled_path -> $user_path"
|
||||
|
||||
# Special handling for soundpack extension - copy default sounds and configure RC
|
||||
if [[ "$name" == "soundpack" ]]; then
|
||||
local sounds_src="$BUNDLED_DIR/sounds"
|
||||
local sounds_dst="$DATA_DIR/sounds"
|
||||
local config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/ttyverse"
|
||||
local rc_file="$config_dir/ttyverserc"
|
||||
|
||||
# Copy sound files
|
||||
if [[ -d "$sounds_src" ]]; then
|
||||
echo " Copying bundled sound files..."
|
||||
cp -r "$sounds_src"/* "$sounds_dst/" 2>/dev/null || true
|
||||
echo -e "${GREEN}✓${NC} Copied default sound pack to $sounds_dst/"
|
||||
fi
|
||||
|
||||
# Auto-configure RC file
|
||||
mkdir -p "$config_dir"
|
||||
local needs_config=false
|
||||
|
||||
# Check if soundpack extension is already configured
|
||||
# Need to check for exts, notifytype, and notifies all being properly set
|
||||
local has_exts=false
|
||||
local has_notifytype=false
|
||||
local has_notifies=false
|
||||
|
||||
if [[ -f "$rc_file" ]]; then
|
||||
grep -q "^exts.*soundpack" "$rc_file" 2>/dev/null && has_exts=true
|
||||
grep -q "^notifytype=.*soundpack" "$rc_file" 2>/dev/null && has_notifytype=true
|
||||
grep -q "^notifies=.*mention.*boost.*favourite" "$rc_file" 2>/dev/null && has_notifies=true
|
||||
fi
|
||||
|
||||
if [[ "$has_exts" == "false" ]] || [[ "$has_notifytype" == "false" ]] || [[ "$has_notifies" == "false" ]]; then
|
||||
needs_config=true
|
||||
fi
|
||||
|
||||
if [[ "$needs_config" == "true" ]]; then
|
||||
echo " Configuring TTYverse for sound notifications..."
|
||||
|
||||
# Create backup if RC file exists
|
||||
[[ -f "$rc_file" ]] && cp "$rc_file" "$rc_file.backup.$(date +%s)"
|
||||
|
||||
# Update or create exts line
|
||||
if [[ -f "$rc_file" ]] && grep -q "^exts=" "$rc_file"; then
|
||||
# Check if soundpack is already in exts line
|
||||
if ! grep -q "^exts=.*soundpack" "$rc_file"; then
|
||||
sed -i 's/^exts=\(.*\)/exts=\1,soundpack/' "$rc_file"
|
||||
echo " Added soundpack to existing exts line"
|
||||
fi
|
||||
else
|
||||
# Add new exts line
|
||||
echo "exts=soundpack" >> "$rc_file"
|
||||
echo " Added exts=soundpack"
|
||||
fi
|
||||
|
||||
# Add or update notifytype
|
||||
if [[ -f "$rc_file" ]] && grep -q "^notifytype=" "$rc_file"; then
|
||||
sed -i 's/^notifytype=.*/notifytype=soundpack/' "$rc_file"
|
||||
echo " Updated notifytype to soundpack"
|
||||
else
|
||||
echo "notifytype=soundpack" >> "$rc_file"
|
||||
echo " Added notifytype=soundpack"
|
||||
fi
|
||||
|
||||
# Add or update notifies parameter for sound events
|
||||
if [[ -f "$rc_file" ]] && grep -q "^notifies=" "$rc_file"; then
|
||||
# Update existing notifies line to include fediverse sound types
|
||||
sed -i 's/^notifies=.*/notifies=default,mention,dm,me,follow,boost,favourite/' "$rc_file"
|
||||
echo " Updated existing notifies configuration"
|
||||
else
|
||||
# Add new notifies line
|
||||
echo "notifies=default,mention,dm,me,follow,boost,favourite" >> "$rc_file"
|
||||
echo " Added notifies configuration"
|
||||
fi
|
||||
|
||||
# Add extension preferences
|
||||
{
|
||||
echo ""
|
||||
echo "# Sound notifications (added by extension manager)"
|
||||
echo "extpref_sound_command=paplay"
|
||||
echo "extpref_soundpack=default"
|
||||
echo ""
|
||||
echo "# Fediverse sound types: default, mention, dm, me, follow, boost, favourite, poll, announcement"
|
||||
} >> "$rc_file"
|
||||
|
||||
echo -e "${GREEN}✓${NC} Configured TTYverse RC file for sound notifications"
|
||||
echo " Restart TTYverse to enable sounds automatically"
|
||||
else
|
||||
echo -e "${YELLOW}Note:${NC} Soundpack already configured in RC file"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
disable_extension() {
|
||||
local name="$1"
|
||||
local ext_file="$name.pl"
|
||||
local user_path="$EXT_DIR/$ext_file"
|
||||
|
||||
if [[ ! -e "$user_path" ]]; then
|
||||
echo -e "${YELLOW}Warning:${NC} Extension '$name' is not enabled"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -L "$user_path" ]]; then
|
||||
rm "$user_path"
|
||||
echo -e "${GREEN}✓${NC} Disabled extension: $name"
|
||||
|
||||
# Special handling for soundpack - offer to remove from RC file
|
||||
if [[ "$name" == "soundpack" ]]; then
|
||||
local config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/ttyverse"
|
||||
local rc_file="$config_dir/ttyverserc"
|
||||
|
||||
if [[ -f "$rc_file" ]] && grep -q "soundpack" "$rc_file"; then
|
||||
echo -e "${YELLOW}Note:${NC} Soundpack is still configured in $rc_file"
|
||||
echo " You may want to remove the soundpack lines to fully disable"
|
||||
echo " Or run TTYverse without -exts=soundpack to override"
|
||||
fi
|
||||
fi
|
||||
elif [[ -f "$user_path" ]]; then
|
||||
echo -e "${YELLOW}Warning:${NC} '$name' is a user-installed extension (not a symlink)"
|
||||
echo "Remove manually if needed: $user_path"
|
||||
fi
|
||||
}
|
||||
|
||||
show_status() {
|
||||
local name="$1"
|
||||
local ext_file="$name.pl"
|
||||
local bundled_path="$BUNDLED_DIR/$ext_file"
|
||||
local user_path="$EXT_DIR/$ext_file"
|
||||
|
||||
echo "Extension: $name"
|
||||
echo "Bundled: $([[ -f "$bundled_path" ]] && echo "Available" || echo "Not found")"
|
||||
|
||||
if [[ -L "$user_path" ]]; then
|
||||
echo -e "Status: ${GREEN}Enabled${NC} (symlinked)"
|
||||
echo "Target: $(readlink "$user_path")"
|
||||
elif [[ -f "$user_path" ]]; then
|
||||
echo -e "Status: ${GREEN}Enabled${NC} (user-installed)"
|
||||
else
|
||||
echo -e "Status: ${YELLOW}Disabled${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main command handling
|
||||
case "${1:-help}" in
|
||||
list|ls)
|
||||
list_extensions
|
||||
;;
|
||||
enable)
|
||||
if [[ -z "$2" ]]; then
|
||||
echo -e "${RED}Error:${NC} Extension name required"
|
||||
echo "Usage: $0 enable <extension_name>"
|
||||
exit 1
|
||||
fi
|
||||
enable_extension "$2"
|
||||
;;
|
||||
disable)
|
||||
if [[ -z "$2" ]]; then
|
||||
echo -e "${RED}Error:${NC} Extension name required"
|
||||
echo "Usage: $0 disable <extension_name>"
|
||||
exit 1
|
||||
fi
|
||||
disable_extension "$2"
|
||||
;;
|
||||
status)
|
||||
if [[ -z "$2" ]]; then
|
||||
echo -e "${RED}Error:${NC} Extension name required"
|
||||
echo "Usage: $0 status <extension_name>"
|
||||
exit 1
|
||||
fi
|
||||
show_status "$2"
|
||||
;;
|
||||
help|--help|-h)
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Error:${NC} Unknown command: $1"
|
||||
echo "Run '$0 help' for usage information"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,76 @@
|
||||
# TTYverse Sound Pack Extension
|
||||
# Adapted from the original TTYtter soundpack by Storm Dragon: https://stormux.org/
|
||||
# Support Storm Dragon's work: https://patreon.com/stormux
|
||||
# Published under the Floodgap Free Software License: http://www.floodgap.com/software/ffsl/
|
||||
|
||||
# Plays sounds for different fediverse activities:
|
||||
# Core: default, mention, dm, me
|
||||
# Fediverse: follow, boost, favourite, poll, announcement
|
||||
#
|
||||
# Configure in RC file with:
|
||||
# extpref_sound_command=paplay # Sound command (paplay, play, ogg123, etc.)
|
||||
# extpref_soundpack=default # Sound pack name
|
||||
# notifytype=soundpack # Enable sound notifications
|
||||
# notifies=default,mention,dm,me,follow,boost,favourite
|
||||
|
||||
sub notifier_soundpack {
|
||||
my $class = shift;
|
||||
my $text = shift;
|
||||
my $ref = shift;
|
||||
|
||||
# Debug output
|
||||
print $stdout "-- DEBUG: soundpack notifier called with class='$class'\n" if (defined($class) && $verbose);
|
||||
|
||||
# Determine sound command (default to paplay for modern Linux)
|
||||
my $sound_command;
|
||||
if (!$extpref_sound_command) {
|
||||
$sound_command = "paplay"; # Modern default for PulseAudio
|
||||
} else {
|
||||
$sound_command = $extpref_sound_command;
|
||||
}
|
||||
|
||||
# Determine sound pack name
|
||||
my $sound_pack;
|
||||
if (!$extpref_soundpack) {
|
||||
$sound_pack = "default";
|
||||
} else {
|
||||
$sound_pack = $extpref_soundpack;
|
||||
}
|
||||
|
||||
# Skip if silent mode enabled
|
||||
return 1 if ($silent);
|
||||
|
||||
if (!defined($class)) {
|
||||
# Initialize - show loaded message
|
||||
print $stdout "-- TTYverse sound pack loaded: $sound_pack\n";
|
||||
print $stdout "-- Supported sounds: default, mention, dm, me, follow, boost, favourite, poll, announcement\n" if (!$silent);
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Build sound file path using XDG data directory
|
||||
my $data_dir = "$ENV{'HOME'}/.local/share/ttyverse";
|
||||
my $sound_file = "$data_dir/sounds/$sound_pack/" . lc($class) . ".ogg";
|
||||
|
||||
if (!-f $sound_file) {
|
||||
# Only warn once per session per class
|
||||
my $warn_key = "warned_missing_sound_$class";
|
||||
if (!$store->{$warn_key}) {
|
||||
print $stdout "-- Warning: Sound file '$class.ogg' not found in pack '$sound_pack'\n";
|
||||
print $stdout "-- Place sound files in $data_dir/sounds/$sound_pack/\n";
|
||||
$store->{$warn_key} = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Play the sound in background (suppress output)
|
||||
print $stdout "-- DEBUG: Playing sound: $sound_command \"$sound_file\"\n" if ($verbose);
|
||||
system("$sound_command \"$sound_file\" >/dev/null 2>&1 &");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
# Mark extension as successfully loaded
|
||||
$store->{'loaded'} = 1;
|
||||
|
||||
# Extension loaded successfully
|
||||
1;
|
||||
@@ -0,0 +1,4 @@
|
||||
*.wav filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
||||
*.opus filter=lfs diff=lfs merge=lfs -text
|
||||
*.ogg filter=lfs diff=lfs merge=lfs -text
|
||||
@@ -0,0 +1,119 @@
|
||||
# TTYverse Sound Packs
|
||||
|
||||
TTYverse supports audio notifications for different types of fediverse activity. Sound packs are collections of audio files that play when specific events occur.
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Enable sounds**: Use the extension manager to enable the soundpack extension:
|
||||
```bash
|
||||
./extensions/manage-extensions.sh enable soundpack
|
||||
```
|
||||
|
||||
2. **Configure TTYverse**: Add to your `~/.config/ttyverse/ttyverserc`:
|
||||
```
|
||||
notifytype=soundpack
|
||||
notifies=default,mention,dm,me,search,follow,boost,favourite
|
||||
extpref_soundpack=default
|
||||
extpref_sound_command=paplay
|
||||
```
|
||||
|
||||
3. **Test**: Start TTYverse and you should hear sounds for different activities!
|
||||
|
||||
## Sound Pack Structure
|
||||
|
||||
Sound packs are stored in `~/.local/share/ttyverse/sounds/` with this structure:
|
||||
```
|
||||
sounds/
|
||||
├── default/ # Default sound pack (included)
|
||||
│ ├── default.ogg # Regular posts
|
||||
│ ├── mention.ogg # @mentions of you
|
||||
│ ├── dm.ogg # Direct messages
|
||||
│ ├── me.ogg # Your own posts
|
||||
│ ├── follow.ogg # New followers
|
||||
│ ├── boost.ogg # Your posts boosted
|
||||
│ ├── favourite.ogg # Your posts favourited
|
||||
│ ├── poll.ogg # Poll notifications
|
||||
│ └── announcement.ogg # Server announcements
|
||||
├── custom/ # Your custom sound pack
|
||||
│ └── *.ogg
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Required Sound Files
|
||||
|
||||
### Core Sounds (Essential)
|
||||
- **`default.ogg`** - Regular timeline posts
|
||||
- **`mention.ogg`** - When someone @mentions you
|
||||
- **`dm.ogg`** - Direct messages received
|
||||
- **`me.ogg`** - Your own posts (optional feedback)
|
||||
|
||||
### Fediverse Interaction Sounds
|
||||
- **`follow.ogg`** - Someone follows you
|
||||
- **`boost.ogg`** - Someone boosts (shares) your post
|
||||
- **`favourite.ogg`** - Someone favourites (likes) your post
|
||||
- **`poll.ogg`** - Poll results or poll you voted in ends
|
||||
- **`announcement.ogg`** - Server announcements
|
||||
|
||||
## Creating Custom Sound Packs
|
||||
|
||||
1. **Create directory**: Make a new directory under `sounds/` with your pack name:
|
||||
```bash
|
||||
mkdir -p ~/.local/share/ttyverse/sounds/mystyle
|
||||
```
|
||||
|
||||
2. **Add sound files**: Place `.ogg` files with the required names. All files should be:
|
||||
- **Format**: OGG Vorbis (most compatible)
|
||||
- **Length**: 1-3 seconds recommended (short and sweet)
|
||||
- **Volume**: Normalized to prevent startling users
|
||||
- **Sample Rate**: 44.1kHz or 48kHz
|
||||
|
||||
3. **Configure TTYverse**: Update your config to use the new pack:
|
||||
```
|
||||
extpref_soundpack=mystyle
|
||||
```
|
||||
|
||||
4. **Test**: Restart TTYverse to load the new sounds
|
||||
|
||||
## Audio Format Support
|
||||
|
||||
TTYverse uses your system's audio command for playback. Supported formats depend on your audio player:
|
||||
|
||||
- **paplay** (PulseAudio default): OGG, WAV, FLAC
|
||||
- **play** (SoX): Most formats including MP3, OGG, WAV
|
||||
- **ogg123**: OGG Vorbis only
|
||||
- **mpv**: Most formats including MP3, OGG, WAV, FLAC
|
||||
|
||||
Configure your preferred player with:
|
||||
```
|
||||
extpref_sound_command=paplay # or play, ogg123, mpv, etc.
|
||||
```
|
||||
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### No Sound
|
||||
1. Check audio command: `paplay /usr/share/sounds/alsa/Front_Left.wav`
|
||||
2. Verify sound pack path: `ls ~/.local/share/ttyverse/sounds/`
|
||||
3. Check TTYverse config: `grep -E "(notifytype|soundpack)" ~/.config/ttyverse/ttyverserc`
|
||||
4. Test with verbose mode: TTYverse will show warnings for missing sounds
|
||||
|
||||
### Wrong Sounds Playing
|
||||
- Verify file names exactly match the required names (case-sensitive)
|
||||
- Check that you're using the correct sound pack name in config
|
||||
- Restart TTYverse after changing sound files
|
||||
|
||||
### Performance Issues
|
||||
- Use compressed formats like OGG instead of WAV
|
||||
- Keep sound files under 3 seconds
|
||||
- Use `&` in sound command for background playback (already handled by extension)
|
||||
|
||||
## Example Sound Pack Themes
|
||||
|
||||
### **Retro Gaming**
|
||||
Use classic 8-bit style beeps and boops for different actions
|
||||
|
||||
### **Natural Sounds**
|
||||
Bird calls, water drops, wind chimes for a calming experience
|
||||
|
||||
### **Minimal**
|
||||
Simple tones with different pitches for each notification type
|
||||
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -0,0 +1,60 @@
|
||||
# TTYverse Timestamp Extension
|
||||
# Modified by Storm Dragon: https://stormux.org/
|
||||
# Support Storm Dragon's work: https://patreon.com/stormux
|
||||
# Original concept from kosertech.com (see ttyverse.wiki/Extension-Development.md for development guide)
|
||||
# Published under the Floodgap Free Software License: http://www.floodgap.com/software/ffsl/
|
||||
|
||||
# What is it?
|
||||
# This extension adds timestamps before posts when 5 minutes or more have passed
|
||||
# between timeline updates, helping organize the flow of your fediverse timeline.
|
||||
|
||||
# Usage:
|
||||
# This extension works automatically. Load it when you start TTYverse or add it
|
||||
# to your configuration. The timestamp format is: -- HH:MMAM/PM --
|
||||
|
||||
$handle = sub {
|
||||
my $delayInSeconds = 60 * 5; # 5 minutes default
|
||||
my ($nsec,$nmin,$nhour,$nday,$nmon,$nyear) = localtime(time);
|
||||
|
||||
# Initialize timestamp tracking on first run
|
||||
if(!$Lib_firstrun){
|
||||
$Lib_firstrun = 1;
|
||||
print "-- TTYverse timestamp extension loaded\n" if (!$silent);
|
||||
$Lib_past = time;
|
||||
}
|
||||
|
||||
# Print timestamp if enough time has elapsed
|
||||
if($Lib_past < (time - $delayInSeconds)){
|
||||
$Lib_past = time;
|
||||
my $timeString = "-- ";
|
||||
my $timeOfDay = "AM";
|
||||
|
||||
# Convert to 12-hour format
|
||||
if ($nhour >= 12) {
|
||||
if ($nhour > 12) {
|
||||
$nhour = $nhour - 12;
|
||||
}
|
||||
$timeOfDay = "PM";
|
||||
}
|
||||
if (($nhour < 10) && ($nhour != 0)) {
|
||||
$timeString .= "0";
|
||||
}
|
||||
if ($nhour == 0) {
|
||||
$nhour = 12;
|
||||
$timeOfDay = "AM";
|
||||
}
|
||||
|
||||
$timeString .= "$nhour:";
|
||||
if ($nmin < 10) {
|
||||
$timeString .= "0";
|
||||
}
|
||||
$timeString .= "$nmin$timeOfDay";
|
||||
print $streamout "$timeString --\n" if (!$silent);
|
||||
}
|
||||
|
||||
# Allow TTYverse to handle displaying the post normally
|
||||
my $ref = shift;
|
||||
&defaulthandle($ref);
|
||||
|
||||
return 1;
|
||||
};
|
||||
@@ -0,0 +1,153 @@
|
||||
# TTYverse Text-to-Speech Extension
|
||||
# By Storm Dragon: https://stormux.org/
|
||||
# Support Storm Dragon's work: https://patreon.com/stormux
|
||||
# Published under the Floodgap Free Software License: http://www.floodgap.com/software/ffsl/
|
||||
|
||||
# What is it?
|
||||
# This extension uses text-to-speech to read incoming fediverse posts.
|
||||
# Multiple synthesizer engines are supported for accessibility.
|
||||
|
||||
# Usage:
|
||||
# Toggle TTS on/off: /tts
|
||||
# Get help: /tts help
|
||||
# Load extension when starting TTYverse or add to configuration
|
||||
|
||||
$addaction = sub {
|
||||
my $command = shift;
|
||||
my $speak = "";
|
||||
|
||||
# Get current TTS state from config
|
||||
my $tts_config = "$ENV{'HOME'}/.config/ttyverse/tts_enabled";
|
||||
if (-e $tts_config) {
|
||||
open TTSSETTINGS, $tts_config;
|
||||
$speak = <TTSSETTINGS>;
|
||||
close TTSSETTINGS;
|
||||
chomp($speak) if defined($speak);
|
||||
} else {
|
||||
$speak = 0;
|
||||
}
|
||||
|
||||
if ($command eq '/tts') {
|
||||
if ((!defined($speak)) || ($speak eq 1)) {
|
||||
$speak = 0;
|
||||
print $streamout "-- Text-to-speech disabled\n";
|
||||
} else {
|
||||
$speak = 1;
|
||||
print $streamout "-- Text-to-speech enabled\n";
|
||||
}
|
||||
|
||||
# Save new state
|
||||
open TTSSETTINGS, ">$tts_config";
|
||||
print TTSSETTINGS "$speak";
|
||||
close TTSSETTINGS;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ($command eq "/tts help") {
|
||||
my $ttsHelp = "TTYverse Text-to-Speech Extension\n\n" .
|
||||
"Commands:\n" .
|
||||
" /tts - Toggle speech on/off\n" .
|
||||
" /tts help - Show this help\n\n" .
|
||||
"Configuration (add to TTYverse config):\n\n" .
|
||||
"extpref_tts_synthesizer=synthName\n" .
|
||||
" Available: espeak (default), festival, pico, cepstral, mac\n\n" .
|
||||
"extpref_tts_language=languageCode\n" .
|
||||
" Default: en-US (supported by espeak and pico)\n\n" .
|
||||
"extpref_tts_rate=number\n" .
|
||||
" Speech rate, default: 175 (espeak only)\n\n" .
|
||||
"extpref_tts_variant=name\n" .
|
||||
" Voice variant/name (espeak variants, cepstral/mac voices)\n";
|
||||
print $streamout "$ttsHelp";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
$handle = sub {
|
||||
my $ref = shift;
|
||||
my $class = shift;
|
||||
|
||||
# Skip TTS during initial timeline load
|
||||
if ($last_id eq 0) {
|
||||
&defaulthandle($ref);
|
||||
return 1;
|
||||
}
|
||||
|
||||
my $speak = "";
|
||||
# Get TTS state from config
|
||||
my $tts_config = "$ENV{'HOME'}/.config/ttyverse/tts_enabled";
|
||||
if (-e $tts_config) {
|
||||
open TTSSETTINGS, $tts_config;
|
||||
$speak = <TTSSETTINGS>;
|
||||
close TTSSETTINGS;
|
||||
chomp($speak) if defined($speak);
|
||||
} else {
|
||||
$speak = 0;
|
||||
}
|
||||
|
||||
# Initialize TTS configuration
|
||||
my $soundCommand = "paplay"; # Default for modern Linux/PulseAudio
|
||||
my $synthesizer = $extpref_tts_synthesizer || "espeak";
|
||||
my $language = $extpref_tts_language || "en-US";
|
||||
my $variant = $extpref_tts_variant || "";
|
||||
my $rate = $extpref_tts_rate || "";
|
||||
|
||||
# Override sound command if configured
|
||||
if ($extpref_sound_command) {
|
||||
$soundCommand = $extpref_sound_command;
|
||||
}
|
||||
|
||||
# Extract post content for TTS
|
||||
my $postText = &descape($ref->{'account'}->{'display_name'} || $ref->{'account'}->{'username'}) .
|
||||
" posted: " . &descape($ref->{'content'});
|
||||
|
||||
# Make speech more accessible
|
||||
$postText =~ s/\"/ /g; # Remove quotes
|
||||
$postText =~ s/ \#/ hashtag /g; # Make hashtags readable
|
||||
$postText =~ s/https?:\/\/\S+/ link /g; # Simplify links
|
||||
$postText =~ s/www\./ /g; # Remove www
|
||||
$postText =~ s/\// forward slash /g; # Make slashes readable
|
||||
$postText =~ s/\\/ back slash /g; # Make backslashes readable
|
||||
$postText =~ s/\blol\b/ laughs out loud /gi; # Expand common abbreviations
|
||||
$postText =~ s/\brofl\b/ rolling on the floor laughing /gi;
|
||||
$postText =~ s/<[^>]*>//g; # Remove any remaining HTML
|
||||
|
||||
my $speechCommand = "";
|
||||
|
||||
# Configure synthesizer command
|
||||
if ($synthesizer eq "cepstral") {
|
||||
$speechCommand = "aoss swift ";
|
||||
if ($variant ne "") {
|
||||
$speechCommand .= "-n $variant ";
|
||||
}
|
||||
$speechCommand .= "\"$postText\"";
|
||||
} elsif ($synthesizer eq "espeak") {
|
||||
if ($rate eq "") {
|
||||
$rate = "175";
|
||||
}
|
||||
$speechCommand = "$synthesizer -v " . lc($language);
|
||||
if ($variant ne "") {
|
||||
$speechCommand .= "+$variant";
|
||||
}
|
||||
$speechCommand .= " -s $rate \"$postText\"";
|
||||
} elsif ($synthesizer eq "festival") {
|
||||
$speechCommand = "echo \"$postText\" | festival --tts";
|
||||
} elsif ($synthesizer eq "mac") {
|
||||
$speechCommand = "say ";
|
||||
if ($variant ne "") {
|
||||
$speechCommand .= "-v $variant ";
|
||||
}
|
||||
$speechCommand .= "\"$postText\"";
|
||||
} elsif ($synthesizer eq "pico") {
|
||||
$speechCommand = "pico2wave -l $language -w /tmp/ttyverse.wav \"$postText\" && $soundCommand /tmp/ttyverse.wav";
|
||||
}
|
||||
|
||||
# Speak the post if TTS is enabled
|
||||
if ($speak eq 1) {
|
||||
system("$speechCommand");
|
||||
}
|
||||
|
||||
# Allow TTYverse to display the post normally
|
||||
&defaulthandle($ref);
|
||||
return 1;
|
||||
};
|
||||
Reference in New Issue
Block a user