bitzdots
gitlabLean Hyprland dotfiles with automatic matugen theming. Low-end optimized, full-stack auto-coloring, 26 Jinja2 templates. Rofi-powered menus, waybar modules, screenshot/recording, event-driven cache daemon.
clone
https://gitlab.com/bitzzdev/bitzdots.gitarchlinuxdotfileshyprlandhyprland-dotfileslow-endminimalricingwallustwaybarwayland
#!/bin/bash# Rofi wallpaper selector with automatic theme generation via matugenCONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}"WALL_DIR="${WALLPAPER_DIR:-$HOME/Pictures/Wallpapers}"CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}"THEME_CACHE="$CACHE_DIR/matugen/themes"ROFI_THEME="$CONFIG_DIR/rofi/themes/wallpaper-grid.rasi"ROFI_POWER="$CONFIG_DIR/rofi/themes/power.rasi"LIVE_DIR="$WALL_DIR/live"THUMB_DIR="$CACHE_DIR/matugen-thumbs"LOG_DIR="$CACHE_DIR/matugen"LOG_FILE="$LOG_DIR/wallpaper-select.log"mkdir -p "$CACHE_DIR" "$THUMB_DIR" "$THEME_CACHE" "$LOG_DIR"alert() {local urgency="${2:-normal}"local title="$1"local msg="$3"echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$urgency] $title${msg:+ - $msg}" >> "$LOG_FILE"echo "[wallpaper-select] $title${msg:+ - $msg}" >&2notify-send -u "$urgency" "$title" "$msg" 2>/dev/null || true}if [ ! -d "$WALL_DIR" ]; thenalert "Wallpapers not found" critical "Directory $WALL_DIR does not exist"exit 1fiMATUGEN_OUTPUTS=("waybar/style.css""waybar/config.jsonc""swaync/style.css""wlogout/style.css""hypr/colors.lua""kitty/colors.conf""cava/themes/generated""rofi/theme-generated.rasi""matugen/env""matugen/browser-colors.css""matugen/chromium-theme.json""rofi/themes/wallpaper-grid.rasi""rofi/themes/power.rasi""rofi/themes/launcher.rasi""rofi/themes/clipboard.rasi""rofi/icons/lock.svg""rofi/icons/logout.svg""rofi/icons/sleep.svg""rofi/icons/reboot.svg""rofi/icons/shutdown.svg""rofi/icons/cancel.svg""rofi/icons/static.svg""rofi/icons/live.svg""kdeglobals""bitzdots.colors""qt6ct/qt6ct.conf")backup_theme() {local backup_dir="$CACHE_DIR/matugen-backup"rm -rf "$backup_dir"for output in "${MATUGEN_OUTPUTS[@]}"; dolocal src="$CONFIG_DIR/$output"if [ -f "$src" ]; thenlocal dst="$backup_dir/$output"mkdir -p "$(dirname "$dst")"cp "$src" "$dst"fidone}restore_theme() {local backup_dir="$CACHE_DIR/matugen-backup"if [ ! -d "$backup_dir" ]; thenreturnfifor output in "${MATUGEN_OUTPUTS[@]}"; dolocal src="$backup_dir/$output"local dst="$CONFIG_DIR/$output"if [ -f "$src" ]; thenmkdir -p "$(dirname "$dst")"cp "$src" "$dst"fidonerm -rf "$backup_dir"}clear_backup() {rm -rf "$CACHE_DIR/matugen-backup"}apply_cached_theme() {local name="$1"local cache_dir="$THEME_CACHE/$name"local marker="$cache_dir/.done"if [ ! -f "$marker" ]; thenreturn 1fi# Invalidate cache if templates changed since it was madelocal template_dir="$CONFIG_DIR/matugen/templates"local latest=0for f in "$template_dir"/*; do[ -f "$f" ] || continuelocal tt=$(stat -c '%Y' "$f")[ "$t" -gt "$latest" ] && latest=$tdonelocal cache_timecache_time=$(stat -c '%Y' "$marker")if [ "$latest" -gt "$cache_time" ]; thenrm -rf "$cache_dir"return 1fifor output in "${MATUGEN_OUTPUTS[@]}"; dolocal src="$cache_dir/$output"local dst="$CONFIG_DIR/$output"if [ -f "$src" ]; thenmkdir -p "$(dirname "$dst")"cp "$src" "$dst"fidonereturn 0}cache_current_theme() {local name="$1"local cache_dir="$THEME_CACHE/$name"mkdir -p "$cache_dir"for output in "${MATUGEN_OUTPUTS[@]}"; dolocal src="$CONFIG_DIR/$output"if [ -f "$src" ]; thenmkdir -p "$(dirname "$cache_dir/$output")"cp "$src" "$cache_dir/$output"fidonetouch "$cache_dir/.done"}# ── Helper: set static wallpaper ─────────────────────────────────set_static() {local img="$1"local namename="$(basename "$img" | sed 's/\.[^.]*$//')"if ! command -v matugen &>/dev/null; thenalert "matugen not installed" criticalexit 1fiecho "$img" > "$CACHE_DIR/current_wallpaper.txt"ln -sf "$img" "$CACHE_DIR/current_wallpaper.png" 2>/dev/null || true# Stop any running live wallpaper first (awww can't override mpvpaper)pkill mpvpaper 2>/dev/null || trueif command -v awww &>/dev/null; thenif ! pgrep -x awww-daemon > /dev/null; thenawww-daemon &sleep 0.5fiawww img "$img" \--transition-type grow \--transition-pos center \--transition-duration 2 \--transition-fps 60 || truefiif ! apply_cached_theme "$name"; thenalert "Generating theme..." normal "Calculating color palette..."backup_themeif timeout 30 matugen image "$img" --config "$CONFIG_DIR/matugen/config.toml"; thencache_current_theme "$name" || trueclear_backupelserestore_themealert "Theme generation failed" critical "Could not generate colors for this wallpaper"return 1fifi"$CONFIG_DIR/matugen/reload-theme.sh" || truealert "Theme updated" normal "Wallpaper and colors applied"# Restart waybar to pick up new config.jsonc and CSSif pgrep -x waybar > /dev/null; thenpkill -x waybar 2>/dev/null || truesleep 0.3waybar &>/dev/null &fi}# ── Helper: set live wallpaper ───────────────────────────────────set_live() {local video="$1"local namename="$(basename "$video" | sed 's/\.[^.]*$//')"if ! command -v mpvpaper &>/dev/null; thenalert "mpvpaper not installed" critical "Install mpvpaper for live wallpapers"exit 1fiecho "$video" > "$CACHE_DIR/current_wallpaper.txt"pkill mpvpaper 2>/dev/null || truempvpaper -o "loop no-audio" '*' "$video"if command -v ffmpeg &>/dev/null && command -v matugen &>/dev/null; thenlocal frame="$CACHE_DIR/live-frame.jpg"ffmpeg -i "$video" -vframes 1 "$frame" -y 2>/dev/null || trueif [ -f "$frame" ]; thenln -sf "$frame" "$CACHE_DIR/current_wallpaper.png" 2>/dev/null || trueif ! apply_cached_theme "$name"; thenalert "Generating theme..." normal "Calculating color palette..."backup_themeif timeout 30 matugen image "$frame" --config "$CONFIG_DIR/matugen/config.toml"; thencache_current_theme "$name" || trueclear_backupelserestore_themealert "Theme generation failed" critical "Could not generate colors for this wallpaper"return 1fifi"$CONFIG_DIR/matugen/reload-theme.sh" || truealert "Live wallpaper" normal "$(basename "$video")"# Restart waybar to pick up new config.jsonc and CSSif pgrep -x waybar > /dev/null; thenpkill -x waybar 2>/dev/null || truesleep 0.3waybar &>/dev/null &fififi}# ── Generate thumbnail for video ─────────────────────────────────generate_thumb() {local video="$1"local thumb_namethumb_name="$(basename "$video" | sed 's/\.[^.]*$//').jpg"local thumb_path="$THUMB_DIR/$thumb_name"if [ ! -f "$thumb_path" ] && command -v ffmpeg &>/dev/null; thenmkdir -p "$(dirname "$thumb_path")"ffmpeg -i "$video" -vframes 1 -vf "scale=180:-1" "$thumb_path" -y 2>/dev/null || truefiif [ -f "$thumb_path" ]; thenecho "$thumb_path"elseecho "$video"fi}# ── Pick static wallpaper ────────────────────────────────────────pick_static() {local imagesmapfile -t images < <(find "$WALL_DIR" -maxdepth 1 -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.webp" \) | sort)if [ ${#images[@]} -eq 0 ]; thenalert "No wallpapers found" normal "Add images to $WALL_DIR/"return 1filocal selectedselected=$(for f in "${images[@]}"; dolocal thumb="$THUMB_DIR/$(basename "$f" | sed 's/\.[^.]*$//').jpg"local display_namedisplay_name="$(basename "$f")"if [ -f "$thumb" ]; thenecho -ne "$display_name\0icon\x1f$thumb\n"elseecho -ne "$display_name\0icon\x1f$f\n"fidone \| rofi -dmenu -i -p "Wallpapers" -theme "$ROFI_THEME" -show-icons)if [ -z "$selected" ]; thenreturn 1filocal target_file=""for f in "${images[@]}"; doif [ "$(basename "$f")" = "$selected" ] || [ "$f" = "$selected" ]; thentarget_file="$f"breakfidoneif [ -z "$target_file" ] && [ -f "$WALL_DIR/$selected" ]; thentarget_file="$WALL_DIR/$selected"fiif [ -z "$target_file" ] || [ ! -f "$target_file" ]; thenalert "Wallpaper not found" critical "$selected"return 1fiset_static "$target_file"}# ── Pick live wallpaper ──────────────────────────────────────────pick_live() {if [ ! -d "$LIVE_DIR" ]; thenalert "No live wallpapers" critical "Directory $LIVE_DIR does not exist"return 1filocal videosmapfile -t videos < <(find "$LIVE_DIR" -maxdepth 1 -type f \( -iname "*.mp4" -o -iname "*.webm" -o -iname "*.mkv" -o -iname "*.gif" \) | sort)if [ ${#videos[@]} -eq 0 ]; thenalert "No live wallpapers" normal "Add videos to $LIVE_DIR/"return 1filocal selectedselected=$(for f in "${videos[@]}"; dothumb=$(generate_thumb "$f")local display_namedisplay_name="$(basename "$f")"echo -ne "$display_name\0icon\x1f$thumb\n"done \| rofi -dmenu -i -p "Live Wallpapers" -theme "$ROFI_THEME" -show-icons)if [ -z "$selected" ]; thenreturn 1filocal target_file=""for f in "${videos[@]}"; doif [ "$(basename "$f")" = "$selected" ] || [ "$f" = "$selected" ]; thentarget_file="$f"breakfidoneif [ -z "$target_file" ] && [ -f "$LIVE_DIR/$selected" ]; thentarget_file="$LIVE_DIR/$selected"fiif [ -z "$target_file" ] || [ ! -f "$target_file" ]; thenalert "Video not found" critical "$selected"return 1fiset_live "$target_file"}# ── Main menu ────────────────────────────────────────────────────main_menu() {local has_live=false[ -d "$LIVE_DIR" ] && [ "$(find "$LIVE_DIR" -maxdepth 1 -type f 2>/dev/null | wc -l)" -gt 0 ] && has_live=truelocal icons_dir="$CONFIG_DIR/rofi/icons"local choicechoice=$({printf "Static wallpaper\0icon\x1f${icons_dir}/static.svg\n"$has_live && printf "Live wallpaper\0icon\x1f${icons_dir}/live.svg\n"} | rofi -dmenu -i -p "Wallpaper" -theme "$ROFI_POWER" -show-icons \-theme-str 'listview { lines: 2; }')case "$choice" in"Static wallpaper") pick_static ;;"Live wallpaper") pick_live ;;*) exit 0 ;;esac}# ── Entry point ──────────────────────────────────────────────────if [ $# -eq 1 ] && [ -f "$1" ]; thenset_static "$1"elif [ $# -eq 1 ] && [ "$1" = "--live" ]; thenpick_liveelsemain_menufi