Skip to content

Instantly share code, notes, and snippets.

@SergioRibera
Last active April 12, 2024 20:49
Show Gist options
  • Save SergioRibera/e761fd61bc6a632c6b566c32aa25558a to your computer and use it in GitHub Desktop.
Save SergioRibera/e761fd61bc6a632c6b566c32aa25558a to your computer and use it in GitHub Desktop.
This script allow set image or video as background on linux, specially for WM's
#!/bin/bash
#
# author: Sergio Ribera
# github: @SergioRibera
#
set -e
export SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )"
LOGS_PATH="/tmp/wallpaper.log"
PIPE_PATH="/tmp/wallpaper.pipe"
PID_FILE="/tmp/wallpaper.pid"
# Define deafult variables
IMG_BG_PATH="$HOME/Pictures/Backgrounds"
VID_BG_PATH="$HOME/Videos/Backgrounds"
TIME_DELAY=30m
VIDEO_SPEED='1'
VIDEO_VOLUME='30'
GIF_PARAMS=''
MPV_PARAMS=''
ALLOW_VID_BG=1
ALLOW_IMG_BG=1
ALLOW_GIF_BG=1
BY_MONITOR=0
DEBUG_LEVEL=0
SCREENS=($(xrandr | grep -e 'connected' | sed -e 's/ primary//g' | cut -d" " -f3))
PAUSE='0'
restart() {
info "Restarting wallpaper..."
# detect if xwinwrap is running
if pgrep -f xwinwrap >/dev/null; then
info "xwinwrap is running, killing it..."
killall xwinwrap
info "xwinwrap killed"
fi
info "Restarted"
}
cleanup() {
echo "Cleaning up..."
restart
echo -e "Cleaning up...\n" >> "$LOGS_PATH"
rm -fr "$PIPE_PATH"
rm -fr "$PID_FILE"
}
info() {
if [ $DEBUG_LEVEL -ge 1 ]; then
echo -e "\e[1;32mInfo:\e[0m $1"
echo -e "Info: $1\n" >> "$LOGS_PATH"
fi
}
error() {
if [ $DEBUG_LEVEL -ge 1 ]; then
echo -e "\e[1;31mError:\e[0m $1"
echo -e "Error: $1\n" >> "$LOGS_PATH"
fi
}
help() {
echo "Usage: $0 [OPTION]..."
echo "Set the desktop background to an image or a video"
echo -e "\nIf not work correctly, you can see the details in log file ($LOGS_PATH)\n"
echo " -h, --help display this help and exit"
echo " -i, --image-path set the background path to an image"
echo " -v, --video-path set the background path to a video"
echo " -t, --time-delay TIME set the time delay between images or videos"
echo " -s, --video-speed SPEED set the video speed"
echo " -d, --debug enable debug"
echo " -b, --by-monitor Show unique image wallpaper for each monitor"
echo " --gif-params PARAMS set the gif parameters"
echo " --mpv-params PARAMS set the mpv parameters"
echo " --no-allow-video no allow video background"
echo " --no-allow-image no allow image background"
echo " --no-allow-gif no allow gif background"
echo -e "\nOnly if already running:\n"
echo " -p, --pause pause the video when the window is not focused"
echo " -r, --resume resume the video when the window is focused"
echo " -n, --skip skip the current wallpaper"
exit 0
}
if [[ $# < 1 ]]; then
error "Illegal number of parameters"
help
exit 1
fi
watchpipe() {
if [[ ! -p $PIPE_PATH ]]; then
mkfifo $PIPE_PATH 2>/dev/null
info "Created pipe"
else
error "Pipe already exists"
exit 2
fi
while true; do
if read line; then
case $line in
skip)
changewallpaper
;;
resume)
PAUSE=0
;;
pause)
PAUSE=1
;;
esac
fi
done <"$PIPE_PATH"
}
sendtopipe() {
if [[ ! -p $PIPE_PATH ]]; then
error "Not previous instance exists"
exit 1
fi
echo $1 > $PIPE_PATH
exit 0
} 2>>$LOGS_PATH
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
-i|--image-path)
IMG_BG_PATH="$2"
shift # past argument
shift # past value
;;
-v|--video-path)
VID_BG_PATH="$2"
shift # past argument
shift # past value
;;
-t|--time-delay)
TIME_DELAY="$2"
shift # past argument
shift # past value
;;
-s|--video-speed)
VIDEO_SPEED="$2"
shift # past argument
shift # past value
;;
--volume)
VIDEO_VOLUME="$2"
shift # past argument
shift # past value
;;
--skip)
sendtopipe "skip"
shift # past argument
shift # past value
exit 0
;;
--pause)
sendtopipe "pause"
shift # past argument
shift # past value
exit 0
;;
--resume)
sendtopipe "resume"
shift # past argument
shift # past value
exit 0
;;
--gif-params)
GIF_PARAMS="$2"
shift # past argument
shift # past value
;;
--mpv-params)
MPV_PARAMS="$2"
shift # past argument
shift # past value
;;
--no-allow-video)
ALLOW_VID_BG=0
shift # past argument
;;
--no-allow-image)
ALLOW_IMG_BG=0
shift # past argument
;;
--no-allow-gif)
ALLOW_GIF_BG=0
shift # past argument
;;
-b|--by-monitor)
BY_MONITOR=1
shift # past argument
;;
-d|--debug)
DEBUG_LEVEL=1
shift # past argument
;;
-h|--help)
help
shift # past argument
shift # past value
;;
*) # unknown option
error "Unknown option \"$key\""
help
exit 1
;;
esac
done
# on exit call cleanup
trap cleanup EXIT
# get all images
tmp_img=$(find $IMG_BG_PATH -name '*' -exec file {} \; | grep -o -P '^.+: \w+ image' | cut -d':' -f1)
tmp_videos=$(find $VID_BG_PATH -type f -exec file -N -i -- {} + | sed -n 's!: video/[^:]*$!!p')
# Fix Arr content
IFS=$'\n' tmp_videos=($tmp_videos)
IFS=$'\n' tmp_img=($tmp_img)
# make only one array
declare -a all_bg
all_bg=(${tmp_img[@]} ${tmp_videos[@]})
info "Found ${#all_bg[@]} backgrounds"
info "Found ${#tmp_img[@]} images"
info "Found ${#tmp_videos[@]} videos"
changewallpaper() {
if [[ ${#all_bg[@]} -gt 0 ]]; then
if [[ $ALLOW_IMG_BG -eq 1 ]]; then
count_screens=1
if [[ $BY_MONITOR -eq 1 ]]; then
count_screens=${#SCREENS[@]}
fi
imgToUse=$(shuf -e "${tmp_img[@]}" -n "$count_screens")
info "Setting images as wallpaper: ${imgToUse}"
feh --bg-scale ${imgToUse}
else
for screen in $SCREENS; do
info "Setting wallpaper for Screen with Resolution: $screen"
restart
# randomize the wallpaper
random_bg=$(shuf -e "${all_bg[@]}" -n1)
info "Random wallpaper: $random_bg"
# check if the file is an image or a video
# if it is a video and allow video, set the video background
if [[ $random_bg =~ \.gif$ ]] && [[ $ALLOW_GIF_BG -eq 1 ]]; then # if is a gif
info "Setting gif as wallpaper"
# replace the gif params
GIF_PARAMS=$(echo $GIF_PARAMS | sed -e 's/\$screen/'$screen'/g' | sed -e 's/\$delay/'$TIME_DELAY'/g' | sed -e 's/\$speed/'$VIDEO_SPEED'/g' | sed -e 's/\$volume/'$VIDEO_VOLUME'/g')
xwinwrap -g $screen -fs -fdt -ni -b -nf -un -o 1.0 -- gifview -wid WID "${random_bg}" -a --no-interactive &
elif [[ $random_bg =~ \.mp4$|\.mkv$|\.avi$|\.webm$ ]] && [[ $ALLOW_VID_BG -eq 1 ]]; then
info "Setting video as wallpaper"
# replace variables in the mpv parameters
mpv_params=$(echo $MPV_PARAMS | sed "s/\$screen/$screen/g")
info "mpv params: $mpv_params"
# start the videos
xwinwrap -g $screen -fs -fdt -ni -b -nf -un -o 1.0 -- mpv -wid WID --loop $mpv_params --no-input-terminal --no-input-cursor --no-osc --no-osd-bar --no-resume-playback --no-input-default-bindings --cursor-autohide=no --really-quiet --volume="$VIDEO_VOLUME" -speed "$VIDEO_SPEED" "${random_bg}" &
fi
done
fi
else
error "No images or videos found"
exit 1
fi
} 2>>$LOGS_PATH/err.log
info "Starting..."
info "Screen founded: ${#SCREENS[@]}"
# Initialize listen pipe file
watchpipe &
# Default random image
# for screen in $SCREENS; do
# info "Screens: ${#SCREENS[@]}"
# imgToUse=$(shuf -e "${tmp_img[@]}" -n "${#SCREENS[@]}")
# info "Setting image: ${imgToUse}"
# feh --bg-scale ${imgToUse}
# done
info "Setting wallpaper every $TIME_DELAY"
info "Pause is $PAUSE"
while true; do
if [[ $PAUSE -eq 0 ]]; then
changewallpaper
fi
sleep $TIME_DELAY
done
@SergioRibera
Copy link
Author

SergioRibera commented Dec 31, 2021

Requirements

  • xrandr
  • feh
  • xwinwrap
  • mpv
  • gifview (gifsicle)
  • bash

Usage

First of all, set excecution permissions to file

chmod +x ./wallpaper.sh

I would recommend to remove the .sh and keep only the name wallpaper, for ease and convenience.
Like as:

./wallpaper --help

Options

-h, --help                                    display this help and exit
-i, --image-path                          set the background path to an image
-v, --video-path                          set the background path to a video
-t, --time-delay TIME                 set the time delay between images or videos
-s, --video-speed SPEED         set the video speed
-b, --by-monitor                    Show unique image wallpaper for each monitor
-d, --debug                                enable debug
--gif-params PARAMS              set the gif parameters
--mpv-params PARAMS           set the mpv parameters
--no-allow-video                        no allow video background
--no-allow-image                       no allow image background
--no-allow-gif                             no allow gif background

Only if already running:

-p, --pause                      pause the video when the window is not focused
-r, --resume                     resume the video when the window is focused
-n, --skip                       skip the current wallpaper

MPV Params support

  • $screen = Screen Size each screen connected

GIFVIEW Params support

  • $screen Screen Size each screen connected
  • $delay Time delay as general value (Like as -t/--time-delay param)
  • $volume Volume setting (like as --volume param)
  • $speed Video Speed (like as -s/--video-speed param)

Example to use

./wallpaper.sh -i $HOME/Pictures -v $HOME/Video -t 15m -s '0.7'

./wallpaper.sh -i $HOME/Pictures -t 1h -s '1' --no-allow-video --gif-params "--geometry $screen" --debug

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment