Open AlfredoLlaquet opened 2 years ago
Second version of my version. Now the script works on Plasma, XFCE and MATE besides Cinnamon.
#!/bin/bash
# This script creates an image to span multiple monitors under Cinnamon, MATE, Plasma and XFCE
# It receives only one parameter which can be
# - A single file name : The script resizes and shaves the image to fit the screeens (does it still work? not sure)
# - A directory with potential files: the script selects randomly one file per monitor.
#
#
#Requires:
# ImageMagick
# xrandr
#
# Author: Raul Suarez
# https://www.usingfoss.com/
#
# Much improved to his liking by: Alfredo Llaquet-Alsina
#
# License: GPL v3.0
#SCRIPTNAME=$(basename $_)
SCRIPTNAME=${0##*/}
#====== VALIDATE DEPENDENCIES ===
command -v gsettings >/dev/null 2>&1 ||
{ echo >&2 "This script only works on systems which rely on gsettings. Aborting."; exit 1; }
command -v xrandr >/dev/null 2>&1 ||
{ echo >&2 "This script only works on systems which rely on xrandr. Aborting."; exit 1; }
command -v identify >/dev/null 2>&1 ||
{ echo >&2 "Please install 'imagemagick'. Aborting."; exit 1; }
#====== GLOBAL VARIABLES ===
VERSION=0.2.2
VALID=true
FORMATS="jpg|jpeg|png"
OUTIMG=${HOME}/.cinnamon/backgrounds/multiMonitorBackground.jpg
MONITORS=()
SCREENGEOMETRY=""
DIRECTORY=""
SINGLEIMG=false
VERBOSE=false
LOOP=false
INTERVAL=""
MYLIST=""
TMPFILE="/tmp/alf_images.tmp"
declare -a FILES=()
# Allow extended pattern substitutions
shopt -s extglob
#====== FUNCTIONS ===
showHelp () {
echo "Usage: multiMonitorBackground [OPTIONS] [FILE] [FILE] ...
This script to set up a background image spaning multiple monitors
under Cinnamon. If no parameters are specified: A random file per monitor is
selected from current directory.
Note: Files are scaled and shaved to fit the display area without loosing aspect radio.
It can receive the following parameters:
FILE Files to set as background. FILE paths must be relative to the
DIRECTORY unless they have an absolute path. Each FILE must be
an image file.
- If the script receives less files than the number of monitors
it will cycle through the files repeating them until all
monitors have a file
- If the script receives no files and the parameter -s is not
specified the script will select one random image per active
monitor
-d DIRECTORY A directory containing image files. The
default is the current directory
-s Span a single FILE across monitors.
If no FILE is passed, and the parameter -s is present, a random
file from the DIRECTORY is displayed.
-t SECONDS Time in SECONDS to refresh the background
-version Displays the version number
-verbose Displays additional information
Examples
: put the same image in each monitor
${SCRIPTNAME} mypic.jpg
: span an image across all the monitors
${SCRIPTNAME} mypic.jpg
: select one random image per monitor from the directory indicated
${SCRIPTNAME} -d ~/Pics
: assign each image received to one or more monitors
${SCRIPTNAME} -d ~/Pics pic1.jpg pic2.jpg
Requires:
ImageMagick
xrandr
Author: Raul Suarez
https://www.usingfoss.com/
"
}
readParameters () {
DIRECTORY=""
SINGLEIMG=false
VERBOSE=false
LOOP=false
INTERVAL=""
FILES=()
while [ $# -gt 0 ] ; do
unset OPTIND
unset OPTARG
while getopts :hsv:d:t: options; do
case $options in
h) showHelp
exit 0
;;
v) local SECONDPART="$OPTARG"
[ "${SECONDPART}" != "ersion" ] && [ "${SECONDPART}" != "erbose" ] &&
echo "Invalid parameter -v$SECONDPART." &&
VALID=false
[ ${SECONDPART} == "ersion" ] &&
echo Version ${VERSION} &&
exit 0
[ ${SECONDPART} == "erbose" ] &&
VERBOSE=true
;;
d) DIRECTORY="$OPTARG"
;;
s) SINGLEIMG=true
;;
t) INTERVAL=$((OPTARG))
LOOP=true
;;
:) case $OPTARG in
v) echo "Invalid parameter -v." >&2
;;
t) echo "Parameter -t usage -t <MINUTES>." >&2
;;
d) echo "Parameter -d usage -d <DIRECTORY>." >&2
;;
esac
VALID=false
;;
?) echo "Invalid parameter -$OPTARG." >&2
VALID=false
;;
esac
done
shift $((OPTIND-1))
FILES+=(${1})
shift
done
[ -n "${DIRECTORY}" ] && [ -n "${FILES}" ] && assembleFullFileNames
${VERBOSE} && echo "Directory : ${DIRECTORY}"
${VERBOSE} && [ -n "${FILES}" ] && echo "Files : ${FILES[@]}"
${VERBOSE} && echo "Single image : ${SINGLEIMG}"
${VERBOSE} && ${LOOP} && echo "Refresh every : $((INTERVAL)) seconds"
$VALID && validateParameters
[ -z "${DIRECTORY}" ] && DIRECTORY="."
}
assembleFullFileNames () {
declare -i i=0
for FILE in "${FILES[@]}"
do
if [ "$(readlink -f ${FILE})" != "${FILE}" ]; then
FILES[$i]="${DIRECTORY}/${FILES[$i]}"
fi
i+=1
done
}
createTempFile () {
if [ -z "${MYLIST}" ] || [ ! -f "${TMPFILE}" ] ; then
${VERBOSE} && echo "Creating temp list of files"
MYLIST="done"
ls "${DIRECTORY}" 2>/dev/null 1> "${TMPFILE}"
fi
}
countImagesInDir () {
# local TESTDIR="${1}"
# echo $(ls "${TESTDIR}"/*.jpg "${TESTDIR}"/*.jpeg "${TESTDIR}"/*.png 2>/dev/null | wc -l)
# # echo $(ls "${TESTDIR}"/*.@(${FORMATS}) 2>/dev/null | wc -l)
NUMIM=$(cat ${TMPFILE} | wc -l)
echo ${NUMIM}
}
validateParameters () {
# Use current directory if no directory or files were passed
if [ -z "${DIRECTORY}" ] ; then
DIRECTORY="."
fi
createTempFile
i=$(countImagesInDir)
${VERBOSE} && echo "Num images : ${i}"
# Validate directory
if [ -n "${DIRECTORY}" ] ; then
[ $i -le 0 ] && VALID=false
! ${VALID} &&
echo "ERROR: Invalid directory name \"${DIRECTORY}\" or directory does not contain image files." &&
return 1
fi
# Validate files
if [ -n "${FILES}" ] ; then
for FILE in "${FILES[@]}"
do
[ -f "${FILE}" ] && identify "${FILE}" &>> /dev/null
[ "$?" -ne 0 ] && VALID=false
! ${VALID} &&
echo "ERROR: Invalid file name ${FILE} or file is not an image file." &&
return 1
done
fi
${SINGLEIMG} && [ ${#FILES[@]} -gt 1 ] && echo "Warning single file parameter but two files specified"
return 0
}
getScreenGeometry () {
SCREENGEOMETRY=$(xrandr | grep "Screen 0: " | sed "s/.*current \([0-9]*\) x \([0-9]*\).*/\1x\2/")
}
getMonitorsGeometry () {
local MONITOR
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
MONITORS=()
for MONITOR in $(xrandr --listmonitors | grep "^ [0-9]" | cut -s -d " " -f 4)
do
VARARRAY=($(echo ${MONITOR} | tr '/' '\n' | tr 'x' '\n' | tr '+' '\n'))
MONITORS+=($(echo ${VARARRAY[0]}x${VARARRAY[2]} +${VARARRAY[4]}+${VARARRAY[5]}))
done
IFS=$SAVEIFS
NUMMONITORS=${#MONITORS[@]}
}
# From the directory select as many random files as requested in the input parameter
selectRandomImages () {
local NUMIMAGES=$1
# FILES=($(ls "${DIRECTORY}"/*.@(${FORMATS}) 2>/dev/null | sort -R | tail -n ${NUMIMAGES} | sed "s/\n/ /"))
# FILES=($(ls "${DIRECTORY}"/*.jpg "${DIRECTORY}"/*.jpeg "${DIRECTORY}"/*.png) 2>/dev/null | sort -R | tail -n ${NUMIMAGES} | sed "s/\n/ /"))
# FILES=($(ls "${DIRECTORY}" 2>/dev/null | sort -R | tail -n ${NUMIMAGES} | sed "s/\n/ /"))
# FILES=($(ls "${DIRECTORY}" 2>/dev/null | sort -R | tail -n ${NUMIMAGES} ))
createTempFile
FILES=($(cat /tmp/alf_images.tmp | sort -R | tail -n ${NUMIMAGES} | sed "s/ /_s_p_a_c_e_/g"))
i=0
for FILE in "${FILES[@]}"
do
${VERBOSE} && echo "FILE $i: ${FILE}"
i=$((i+1))
done
}
assembleBackgroundImage () {
local MONITOR
local THISFILE
local TEMPIMG=$(mktemp --suffix=.jpg -p /tmp tmpXXX)
local TEMPOUT=$(mktemp --suffix=.jpg -p /tmp tmpXXX)
# Creates the blank base image
convert -size ${SCREENGEOMETRY} xc:skyblue ${TEMPOUT}
i=0
for MONITOR in "${MONITORS[@]}"
do
${VERBOSE} && echo "i: $i"
j=0
for FILE in "${FILES[@]}"
do
if [ $j -eq $i ] ; then
# THISFILE="${FILE}"
THISFILE=("$(echo ${FILE} | sed "s/_s_p_a_c_e_/ /g")")
${VERBOSE} && echo "THISFILE $j: ${THISFILE}"
fi
j=$((j+1))
done
if [ "${KDE_FULL_SESSION}" == "true" ]; then
if command -v qdbus-qt5 &>/dev/null; then
qdbus_command=qdbus-qt5
else
qdbus_command=qdbus
fi
QT_SELECT=5 $qdbus_command org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript "
var allDesktops = desktops();
allDesktops[$i].wallpaperPlugin = 'org.kde.image';
allDesktops[$i].currentConfigGroup = Array('Wallpaper', 'org.kde.image', 'General');
allDesktops[$i].writeConfig('Image', 'file://""${DIRECTORY}/$THISFILE""');
allDesktops[$i].writeConfig('FillMode', '1');
"
else
GEOMETRY=$(echo ${MONITOR} | cut -s -d " " -f 1)
OFFSET=$(echo ${MONITOR} | cut -s -d " " -f 2)
# ${VERBOSE} && echo "Monitor $i : ${GEOMETRY}${OFFSET} : ${FILES[$i]}"
${VERBOSE} && echo "Monitor $i : ${GEOMETRY}${OFFSET} : ${THISFILE}"
# convert "${DIRECTORY}/${FILES[$i]}" -auto-orient -scale ${GEOMETRY}^ -gravity center -extent ${GEOMETRY} ${TEMPIMG}
# convert "${DIRECTORY}/${FILES[$i]}" -resize ${GEOMETRY} -gravity center -background "rgb(0,0,0)" -extent ${GEOMETRY} ${TEMPIMG}
convert "${DIRECTORY}/${THISFILE}" -resize ${GEOMETRY} -gravity center -background "rgb(0,0,0)" -extent ${GEOMETRY} ${TEMPIMG}
composite -geometry ${OFFSET} ${TEMPIMG} ${TEMPOUT} ${TEMPOUT}
fi
i=$((i+1))
[ $i -ge ${#FILES[@]} ] && i=0
done
rm "${TEMPIMG}"
mv "${TEMPOUT}" "${OUTIMG}"
}
applyBackground () {
if [ "$desktop" == "Cinnamon" ] || [ "$XDG_CURRENT_DESKTOP" == "X-Cinnamon" ]; then
gsettings set org.cinnamon.desktop.background picture-options "spanned"
gsettings set org.cinnamon.desktop.background picture-uri "file://$(readlink -f ${OUTIMG})"
elif [ "$XDG_CURRENT_DESKTOP" == "MATE" ]; then
gsettings set org.mate.background picture-filename "$(readlink -f ${OUTIMG})" 2> /dev/null
elif [ "$desktop" == "xubuntu" ] || [ "$XDG_CURRENT_DESKTOP" == "XFCE" ]; then
rc=$?
if [[ $rc = 0 ]] ; then
for i in $(xfconf-query -c xfce4-desktop -p /backdrop -l | grep -E -e "screen.*/monitor.*image-path$" -e "screen.*/monitor.*/last-image$"); do
xfconf-query -c xfce4-desktop -p "$i" -n -t string -s "" 2> /dev/null
xfconf-query -c xfce4-desktop -p "$i" -s "" 2> /dev/null
xfconf-query -c xfce4-desktop -p "$i" -s "$(readlink -f ${OUTIMG})" 2> /dev/null
done
fi
fi
}
spanSingleImage () {
[ -z "${FILES}" ] && selectRandomImages 1
${VERBOSE} && echo "File : ${FILES[0]}"
convert "${FILES[0]}" -auto-orient -scale ${SCREENGEOMETRY}^ -gravity center -extent ${SCREENGEOMETRY} "${OUTIMG}"
}
assembleOneImagePerMonitor () {
getMonitorsGeometry
[ -z "${FILES}" ] && selectRandomImages ${NUMMONITORS}
assembleBackgroundImage
}
setBackground () {
local ORIGFILES=${FILES}
getScreenGeometry
if ${SINGLEIMG} ; then spanSingleImage
else assembleOneImagePerMonitor
fi
[ -f "${OUTIMG}" ] && applyBackground
FILES=${ORIGFILES}
}
#====== MAIN BODY OF THE SCRIPT ===
readParameters $@
if ${VALID} ; then
if ${LOOP} ; then
while true; do ${VERBOSE} && echo "Let's go"; setBackground ; sleep ${INTERVAL}; done
else
setBackground
fi
else
echo "Use -h for help."
exit 1
fi
Third version of my version. Now the script works on Plasma, XFCE, MATE and GNOME besides Cinnamon.
#!/bin/bash
# This script creates an image to span multiple monitors under Cinnamon
# It receives only one parameter which can be
# - A single file name : The script resizes and shaves the image to fit the screeens
# - A directory with potential files: the script selects randomly one file per monitor.
#
# Note: Files are scaled and shaved to fit the display area without loosing aspect radio.
#
#Requires:
# ImageMagick
# xrandr
#
# Author: Raul Suarez
# https://www.usingfoss.com/
#
# Improved to his liking by: Alfredo Llaquet Alsina
#
# License: GPL v3.0
#SCRIPTNAME=$(basename $_)
SCRIPTNAME=${0##*/}
#====== VALIDATE DEPENDENCIES ===
command -v gsettings >/dev/null 2>&1 ||
{ echo >&2 "This script only works on systems which rely on gsettings. Aborting."; exit 1; }
command -v xrandr >/dev/null 2>&1 ||
{ echo >&2 "This script only works on systems which rely on xrandr. Aborting."; exit 1; }
command -v identify >/dev/null 2>&1 ||
{ echo >&2 "Please install 'imagemagick'. Aborting."; exit 1; }
#====== GLOBAL VARIABLES ===
VERSION=0.2.2
VALID=true
FORMATS="jpg|jpeg|png"
# OUTIMG=${HOME}/.cinnamon/backgrounds/multiMonitorBackground.jpg
OUTIMG=${HOME}/Pictures/multiMonitorBackground.jpg
# OUTIMG=/tmp/multiMonitorBackground.jpg
MONITORS=()
SCREENGEOMETRY=""
DIRECTORY=""
SINGLEIMG=false
VERBOSE=false
LOOP=false
INTERVAL=""
MYLIST=""
TMPFILE="/tmp/alf_images.tmp"
declare -a FILES=()
# Allow extended pattern substitutions
shopt -s extglob
#====== FUNCTIONS ===
showHelp () {
echo "Usage: multiMonitorBackground [OPTIONS] [FILE] [FILE] ...
This script to set up a background image spaning multiple monitors
under Cinnamon. If no parameters are specified: A random file per monitor is
selected from current directory.
Note: Files are scaled and shaved to fit the display area without loosing aspect radio.
It can receive the following parameters:
FILE Files to set as background. FILE paths must be relative to the
DIRECTORY unless they have an absolute path. Each FILE must be
an image file.
- If the script receives less files than the number of monitors
it will cycle through the files repeating them until all
monitors have a file
- If the script receives no files and the parameter -s is not
specified the script will select one random image per active
monitor
-d DIRECTORY A directory containing image files. The
default is the current directory
-s Span a single FILE across monitors.
If no FILE is passed, and the parameter -s is present, a random
file from the DIRECTORY is displayed.
-t SECONDS Time in SECONDS to refresh the background
-version Displays the version number
-verbose Displays additional information
Examples
: put the same image in each monitor
${SCRIPTNAME} mypic.jpg
: span an image across all the monitors
${SCRIPTNAME} mypic.jpg
: select one random image per monitor from the directory indicated
${SCRIPTNAME} -d ~/Pics
: assign each image received to one or more monitors
${SCRIPTNAME} -d ~/Pics pic1.jpg pic2.jpg
Requires:
ImageMagick
xrandr
Author: Raul Suarez
https://www.usingfoss.com/
"
}
readParameters () {
DIRECTORY=""
SINGLEIMG=false
VERBOSE=false
LOOP=false
INTERVAL=""
FILES=()
while [ $# -gt 0 ] ; do
unset OPTIND
unset OPTARG
while getopts :hsv:d:t: options; do
case $options in
h) showHelp
exit 0
;;
v) local SECONDPART="$OPTARG"
[ "${SECONDPART}" != "ersion" ] && [ "${SECONDPART}" != "erbose" ] &&
echo "Invalid parameter -v$SECONDPART." &&
VALID=false
[ ${SECONDPART} == "ersion" ] &&
echo Version ${VERSION} &&
exit 0
[ ${SECONDPART} == "erbose" ] &&
VERBOSE=true
;;
d) DIRECTORY="$OPTARG"
;;
s) SINGLEIMG=true
;;
t) INTERVAL=$((OPTARG))
LOOP=true
;;
:) case $OPTARG in
v) echo "Invalid parameter -v." >&2
;;
t) echo "Parameter -t usage -t <MINUTES>." >&2
;;
d) echo "Parameter -d usage -d <DIRECTORY>." >&2
;;
esac
VALID=false
;;
?) echo "Invalid parameter -$OPTARG." >&2
VALID=false
;;
esac
done
shift $((OPTIND-1))
FILES+=(${1})
shift
done
[ -n "${DIRECTORY}" ] && [ -n "${FILES}" ] && assembleFullFileNames
${VERBOSE} && echo "Directory : ${DIRECTORY}"
${VERBOSE} && [ -n "${FILES}" ] && echo "Files : ${FILES[@]}"
${VERBOSE} && echo "Single image : ${SINGLEIMG}"
${VERBOSE} && ${LOOP} && echo "Refresh every : $((INTERVAL)) seconds"
$VALID && validateParameters
[ -z "${DIRECTORY}" ] && DIRECTORY="."
}
assembleFullFileNames () {
${VERBOSE} && echo "assembleFullFileNames"
declare -i i=0
for FILE in "${FILES[@]}"
do
if [ "$(readlink -f ${FILE})" != "${FILE}" ]; then
FILES[$i]="${DIRECTORY}/${FILES[$i]}"
fi
i+=1
done
}
createTempFile () {
${VERBOSE} && echo "createTempFile"
if [ -z "${MYLIST}" ] || [ ! -f "${TMPFILE}" ] ; then
${VERBOSE} && echo "Creating temp list of files"
MYLIST="done"
ls "${DIRECTORY}" 2>/dev/null 1> "${TMPFILE}"
fi
}
countImagesInDir () {
${VERBOSE} && echo "countImagesInDir"
# local TESTDIR="${1}"
# echo $(ls "${TESTDIR}"/*.jpg "${TESTDIR}"/*.jpeg "${TESTDIR}"/*.png 2>/dev/null | wc -l)
# # echo $(ls "${TESTDIR}"/*.@(${FORMATS}) 2>/dev/null | wc -l)
NUMIM=$(cat ${TMPFILE} | wc -l)
echo ${NUMIM}
}
validateParameters () {
${VERBOSE} && echo "validateParameters"
# Use current directory if no directory or files were passed
if [ -z "${DIRECTORY}" ] ; then
DIRECTORY="."
fi
createTempFile
i=$(countImagesInDir)
${VERBOSE} && echo "Num images : ${i}"
# Validate directory
if [ -n "${DIRECTORY}" ] ; then
[ $i -le 0 ] && VALID=false
! ${VALID} &&
echo "ERROR: Invalid directory name \"${DIRECTORY}\" or directory does not contain image files." &&
return 1
fi
# Validate files
if [ -n "${FILES}" ] ; then
for FILE in "${FILES[@]}"
do
[ -f "${FILE}" ] && identify "${FILE}" &>> /dev/null
[ "$?" -ne 0 ] && VALID=false
! ${VALID} &&
echo "ERROR: Invalid file name ${FILE} or file is not an image file." &&
return 1
done
fi
${SINGLEIMG} && [ ${#FILES[@]} -gt 1 ] && echo "Warning single file parameter but two files specified"
return 0
}
getScreenGeometry () {
${VERBOSE} && echo "getScreenGeometry"
SCREENGEOMETRY=$(xrandr | grep "Screen 0: " | sed "s/.*current \([0-9]*\) x \([0-9]*\).*/\1x\2/")
}
getMonitorsGeometry () {
${VERBOSE} && echo "getMonitorsGeometry"
local MONITOR
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
MONITORS=()
for MONITOR in $(xrandr --listmonitors | grep "^ [0-9]" | cut -s -d " " -f 4)
do
VARARRAY=($(echo ${MONITOR} | tr '/' '\n' | tr 'x' '\n' | tr '+' '\n'))
MONITORS+=($(echo ${VARARRAY[0]}x${VARARRAY[2]} +${VARARRAY[4]}+${VARARRAY[5]}))
done
IFS=$SAVEIFS
NUMMONITORS=${#MONITORS[@]}
}
# From the directory select as many random files as requested in the input parameter
selectRandomImages () {
${VERBOSE} && echo "selectRandomImages"
local NUMIMAGES=$1
# FILES=($(ls "${DIRECTORY}"/*.@(${FORMATS}) 2>/dev/null | sort -R | tail -n ${NUMIMAGES} | sed "s/\n/ /"))
# FILES=($(ls "${DIRECTORY}"/*.jpg "${DIRECTORY}"/*.jpeg "${DIRECTORY}"/*.png) 2>/dev/null | sort -R | tail -n ${NUMIMAGES} | sed "s/\n/ /"))
# FILES=($(ls "${DIRECTORY}" 2>/dev/null | sort -R | tail -n ${NUMIMAGES} | sed "s/\n/ /"))
# FILES=($(ls "${DIRECTORY}" 2>/dev/null | sort -R | tail -n ${NUMIMAGES} ))
createTempFile
FILES=($(cat /tmp/alf_images.tmp | sort -R | tail -n ${NUMIMAGES} | sed "s/ /_s_p_a_c_e_/g"))
i=0
for FILE in "${FILES[@]}"
do
${VERBOSE} && echo "FILE $i: ${FILE}"
i=$((i+1))
done
}
assembleBackgroundImage () {
${VERBOSE} && echo "assembleBackgroundImage"
local MONITOR
local THISFILE
local TEMPIMG=$(mktemp --suffix=.jpg -p /tmp tmpXXX)
local TEMPOUT=$(mktemp --suffix=.jpg -p /tmp tmpXXX)
# Creates the blank base image
convert -size ${SCREENGEOMETRY} xc:skyblue ${TEMPOUT}
i=0
for MONITOR in "${MONITORS[@]}"
do
${VERBOSE} && echo "i: $i"
j=0
for FILE in "${FILES[@]}"
do
if [ $j -eq $i ] ; then
# THISFILE="${FILE}"
THISFILE=("$(echo ${FILE} | sed "s/_s_p_a_c_e_/ /g")")
${VERBOSE} && echo "THISFILE $j: ${THISFILE}"
fi
j=$((j+1))
done
if [ "${KDE_FULL_SESSION}" == "true" ]; then
if command -v qdbus-qt5 &>/dev/null; then
qdbus_command=qdbus-qt5
else
qdbus_command=qdbus
fi
QT_SELECT=5 $qdbus_command org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript "
var allDesktops = desktops();
allDesktops[$i].wallpaperPlugin = 'org.kde.image';
allDesktops[$i].currentConfigGroup = Array('Wallpaper', 'org.kde.image', 'General');
allDesktops[$i].writeConfig('Image', 'file://""${DIRECTORY}/$THISFILE""');
allDesktops[$i].writeConfig('FillMode', '1');
"
else
GEOMETRY=$(echo ${MONITOR} | cut -s -d " " -f 1)
OFFSET=$(echo ${MONITOR} | cut -s -d " " -f 2)
# ${VERBOSE} && echo "Monitor $i : ${GEOMETRY}${OFFSET} : ${FILES[$i]}"
${VERBOSE} && echo "Monitor $i : ${GEOMETRY}${OFFSET} : ${THISFILE}"
# convert "${DIRECTORY}/${FILES[$i]}" -auto-orient -scale ${GEOMETRY}^ -gravity center -extent ${GEOMETRY} ${TEMPIMG}
# convert "${DIRECTORY}/${FILES[$i]}" -resize ${GEOMETRY} -gravity center -background "rgb(0,0,0)" -extent ${GEOMETRY} ${TEMPIMG}
convert "${DIRECTORY}/${THISFILE}" -resize ${GEOMETRY} -gravity center -background "rgb(0,0,0)" -extent ${GEOMETRY} ${TEMPIMG}
composite -geometry ${OFFSET} ${TEMPIMG} ${TEMPOUT} ${TEMPOUT}
fi
i=$((i+1))
[ $i -ge ${#FILES[@]} ] && i=0
done
rm "${TEMPIMG}"
mv "${TEMPOUT}" "${OUTIMG}"
}
applyBackground () {
${VERBOSE} && echo "applyBakcground"
${VERBOSE} && echo "\$desktop : $desktop"
${VERBOSE} && echo "\$XDG_CURRENT_DESKTOP : $XDG_CURRENT_DESKTOP"
if [ "$desktop" == "Cinnamon" ] || [ "$XDG_CURRENT_DESKTOP" == "X-Cinnamon" ]; then
gsettings set org.cinnamon.desktop.background picture-options "spanned"
gsettings set org.cinnamon.desktop.background picture-uri "file://$(readlink -f ${OUTIMG})"
elif [ "$XDG_CURRENT_DESKTOP" == "GNOME" ]; then
gsettings set org.gnome.desktop.background picture-options "spanned"
gsettings set org.gnome.desktop.background picture-uri "file://$(readlink -f ${OUTIMG})"
gsettings set org.gnome.desktop.background picture-uri-dark "file://$(readlink -f ${OUTIMG})"
elif [ "$XDG_CURRENT_DESKTOP" == "MATE" ]; then
gsettings set org.mate.background picture-filename "$(readlink -f ${OUTIMG})" 2> /dev/null
elif [ "$desktop" == "xubuntu" ] || [ "$XDG_CURRENT_DESKTOP" == "XFCE" ]; then
rc=$?
if [[ $rc = 0 ]] ; then
for i in $(xfconf-query -c xfce4-desktop -p /backdrop -l | grep -E -e "screen.*/monitor.*image-path$" -e "screen.*/monitor.*/last-image$"); do
xfconf-query -c xfce4-desktop -p "$i" -n -t string -s "" 2> /dev/null
xfconf-query -c xfce4-desktop -p "$i" -s "" 2> /dev/null
xfconf-query -c xfce4-desktop -p "$i" -s "$(readlink -f ${OUTIMG})" 2> /dev/null
done
fi
fi
}
spanSingleImage () {
${VERBOSE} && echo "spanSingleImage"
[ -z "${FILES}" ] && selectRandomImages 1
${VERBOSE} && echo "File : ${FILES[0]}"
convert "${FILES[0]}" -auto-orient -scale ${SCREENGEOMETRY}^ -gravity center -extent ${SCREENGEOMETRY} "${OUTIMG}"
}
assembleOneImagePerMonitor () {
${VERBOSE} && echo "assembleOneImagePerMonitor"
getMonitorsGeometry
[ -z "${FILES}" ] && selectRandomImages ${NUMMONITORS}
assembleBackgroundImage
}
setBackground () {
${VERBOSE} && echo "setBackground"
local ORIGFILES=${FILES}
getScreenGeometry
if ${SINGLEIMG} ; then spanSingleImage
else assembleOneImagePerMonitor
fi
[ -f "${OUTIMG}" ] && applyBackground
FILES=${ORIGFILES}
}
#====== MAIN BODY OF THE SCRIPT ===
readParameters $@
if ${VALID} ; then
if ${LOOP} ; then
while true; do ${VERBOSE} && echo "Let's go"; setBackground ; sleep ${INTERVAL}; done
else
setBackground
fi
else
echo "Use -h for help."
exit 1
fi
Hi. I use Cinnamon on Garuda Linux (Arch Linux, basically). I have 3 monitors and a directory with many many images. I don't know almost anything about bash scripting, but with DuckDuckGo and several hours of time I've made the following improvements to suit my needs:
-My version of the script works with directories with tens of thousands of images, like mine. The original script reported an error when this was the case. -The file names of the images now may contain spaces. The original script failed in that situation. -The original script didn't ever work, at least on my computer, because, when it accessed the images at some point, it did not include their path. -The script now, instead of zooming the images to occupy the whole screen, scales the images and fills the remaining space with black. -The original script did not access correctly the array of images and the same image was showing in two of the monitors. Now, a different image shows in each monitor. -In my version of the script, the interval is in seconds. -The original script listed the images every cycle. Now, it creates a temporal file with the listing at the beginning and accesses this file in subsequent cycles (less disk intensive). -My script works with modern image file formats such as webp. -My script has the limitation that it assumes that all files in the images directory are images. That is my case.
My version follows. It works great in my computer and it should also work in others that respect the limitation just mentioned. Feel free to do whatever you want with it: