rWall, a Random Wallpaper Script

About writing shell scripts and making the most of your shell
Forum rules
Topics in this forum are automatically closed 6 months after creation.
Locked
rockhazard
Level 1
Level 1
Posts: 43
Joined: Wed May 04, 2011 1:44 pm

rWall, a Random Wallpaper Script

Post by rockhazard »

Here's a random wallpaper changer that I've tinkered with off and on for a while. It's really a project to help me understand Bash scripting while getting immediate visual feedback. It works with MATE, Cinnamon, Gnome Shell, Unity, KDE4, and Openbox. It will detect what environment you are in automatically, and change the wallpaper accordingly (with some initial setup if you are using KDE). It also has a slideshow function (loop), and you can hotkey its options to change backgrounds from various directories. It requires feh for Openbox, and Yad (a fork of zenity), if you want to use the gui dialogs. I've included a ppa for Yad in the intro, if you want it. Because of the support for MATE and Cinnamon, I figured somebody here might want something like this.
update: enhanced loop function through notification tray icon control
update: updated to work with XFCE 4.10 and Cinnamon 1.9.1; the line testing for "Cinnamon 1.9.1" will have to be changed manually with each new version until I figure out how to handle that.
update: improved reliability of XFCE 4.10 detection.

To use it, just save it to your ~/bin directory, then cd to ~/bin and run

Code: Select all

chmod +x ./rwall
in a terminal.

Let me know what you think!

Code: Select all

#!/bin/bash

#===============================================================================
#
# FILE: rwall
#
# USAGE: rwall [-h] [-v] [-d1] [-d2] [-d3] [-dd] [-l] | IMAGE DIRECTORY
#
# DESCRIPTION:
# rWall automatically detects the current user's environment then selects a 
# random image from a directory.  The script applies that image as a background. 
# It supports GNOME3 (Gnome Shell, Unity, Cinnamon, Mate), KDE4, XFCE 4.10, 
# and Openbox.
#
# KDE support requires some trivial setup via "Default Desktop Settings". 
# Use the slideshow option, set "Change images every" to lowest, and select
# appropriate monitor folder created in the "set_kde" function.
#
# rWall may also work with other environments capable of using feh.
# 
# TODO: fuse with pixwalker.sh to enable file traversing, Yad notification menu
# OPTIONS: see function ’usage’ below
# REQUIREMENTS: feh for Openbox usage, and yad (ppa:webupd8team/y-ppa-manager)
# BUGS: ---
# NOTES: when running KDE, a template folder is created as ~/.config/rwall
# AUTHOR: rockhazard, rockhazardz@gmail.com
# COMPANY: ---
# VERSION: 2.2 "Apu"
# CREATED: Thursday, Aug 7, 2013 12:30 AM
# REVISION: ---
# LICENSE: GPL 2.0
#===============================================================================
# CHANGELOG
# 2.2, Apu: XFCE 4.10 support, Cinnamon 2.0 support, updated KDE support
# 2.0, Krusty: Desktop environment auto-detection, KDE support, Mate 1.4 support
# 1.8, Lisa: Mate support, Yad support, multiple alternate image directories
# 1.5, Bart: GNOME3 support, wallpaper loop function
# 1.0, Homer: Change image directory via commandline 
#===============================================================================

declare VERSION
declare BGDIR            # result of wallpaper commandline argument test
declare WALLPAPER        # result of randomized image selection
declare SETWALL          # command to change background of current desktop
declare USERDIR          # default image directory
declare INTERVAL         # number of times to loop background
declare SPEED            # number of seconds between background changes
declare LOOPDIR          # directory returned by loop dialog
declare -a loopForm      # array returned from yad loop request form
declare loopID           # the slideshow's background process
declare DE               # tag for current desktop environment

VERSION="v2.2 \"Apu\" (c) 2014, by rockhazard"

#HELP
usage() {
  echo " rwall [-h] [-v] [-d1] [-d2] [-d3] [-dd] [-l] | IMAGE DIRECTORY"
  echo
  echo " --help .................. prints this help"
  echo " --version, -v ........... prints version number"
  echo " --directory1, -d1 ....... use first alternate image directory"
  echo " --directory2, -d2 ....... use second alternate image directory"
  echo " --directory3, -d3 ....... use third alternate image directory"
  echo " --dir-dialog, -dd ......... choose an image directory via a GTK dialog"
  echo " --file-dialog, -fd ......... choose an image via a GTK dialog"
  echo " --loop, -l .............. loop background a given number of times"
  echo "                           every given number of seconds"
  echo
  echo " KDE users: Please manually set wallpaper 'slideshow' option to the"
  echo " ~/.config/rwall/kde/mon1 after first run. If you wish to use different" 
  echo " backgrounds on your monitors, just set each desktop to a different"
  echo " template image from inside the rwall directory."
  echo 
}

# PRE-DEFINED DIRECTORIES

# change the directory below to the desired default image directory
USERDIR="$HOME/Pictures"
if [[ ! -d $USERDIR ]]; then
  echo "Please choose a valid default image directory!"
  exit
fi

dir_test() {
  if [[ ! -d $BGDIR ]]; then
  echo "Please provide a valid alternate image directory!"
  exit
  fi
}

# set alternate image directories below, then use options "-d1" through "-d3"
set_directory1() {
  BGDIR="$HOME/Pictures"
  dir_test
}

set_directory2() {
  BGDIR="$HOME/Pictures"
  dir_test
}

set_directory3() {
  BGDIR="$HOME/Pictures"
  # BGDIR="$HOME/Pictures/wallbase/sexy/emma.mae"
  dir_test
}

set_lockscreen() { 
  # breaks BGDIR pattern to avoid conflict with loop
  # and keep lockscreen separate from background image.
  LOCKDIR="$HOME/Pictures"
  if [[ ! -d $LOCKDIR ]]; then
  echo "Please provide a valid lockscreen image directory!"
  exit
  fi
}

# GUI DIALOGS

test_dialog() {
  if [[ ! -x /usr/bin/yad || ! -x /usr/bin/zenity ]]; then
    echo "Please install either yad or zenity to employ gui dialogs."
    exit
  fi
}

cancel_dialog() {
  if [[ $BGDIR == '' ]]; then
    exit
  fi
}

# Zenity dialog for choosing image directory
call_zenity_dialog() {
  test_dialog
  BGDIR=$(zenity --file-selection --directory 
  --title='Pick Your Wallpaper Directory' \
  --width=600 --height=500 \
  --filename="$HOME/Pictures/")
  cancel_dialog  
}

# Yad GTK dialog for choosing image directory
call_dir_dialog() { 
  test_dialog
  BGDIR=$(yad --file --directory \
  --title='Pick Your Wallpaper Directory' \
  --add-preview --borders=3 --width=600 --height=500 \
  --filename="$HOME/Pictures/*")
  cancel_dialog
}

# Yad GTK dialog for picking image file
call_file_dialog() {
  test_dialog
  BGDIR=$(yad --file \
  --title='Pick Your Wallpaper Image' \
  --add-preview --borders=10 --width=700 --height=500 \
  --filename="$HOME/Pictures/*")
  cancel_dialog
}

# SET DESKTOP ENVIRONMENTS

set_kde() {
  # create rWall settings folders, if they don't exist
  if [[ ! -d $HOME/.config/rwall/kde ]]; then
    mkdir -p $HOME/.config/rwall/kde/mon1 &> /dev/null
    mkdir -p $HOME/.config/rwall/kde/mon2 &> /dev/null
  fi

  if [[ ! -e $HOME/.config/rwall/rwall.log ]]; then
    touch $HOME/.config/rwall/rwall.log &> /dev/null
  fi
  LOG="$HOME/.config/rwall/rwall.log"

  # first monitor
  # set KDE wallpaper to path below
  cp $WALLPAPER $HOME/.config/rwall/kde/mon1/rwall-kde.jpg
  echo -e "$(date):\nMonitor1\n$WALLPAPER" >> $LOG

  # second monitor
  # uncomment a set_directory for different image directory 
  # than the first monitor
  # set_directory1
  # set_directory2
  # set_directory3
  random_sort ; cp $WALLPAPER $HOME/.config/rwall/kde/mon2/rwall-monitor2-kde.jpg
  echo -e "$(date):\nMonitor2\n$WALLPAPER" >> $LOG

  # lockscreen
  # to use, uncomment cp line, run once, then set lockscreen to file shown below
  set_lockscreen ; lockscreen_random_sort
  # cp $LOCKSCREEN $HOME/.config/rwall/kde/rwall-lockscreen-kde.jpg
  echo -e "$(date):\nLockscreen\n$LOCKSCREEN\n#####################" >> $LOG
}

set_openbox() {
  # feh --bg-center "$WALLPAPER"
  # feh --bg-scale "$WALLPAPER"
  # feh --bg-tile "$WALLPAPER"
  feh --bg-fill "$WALLPAPER"
}

set_gnome3() {
  # options: centered, none, scaled, spanned, stretched, wallpaper, zoom
  gsettings set org.gnome.desktop.background picture-options 'scaled'

  # change "set"  to "get" and delete option to return current background image
  gsettings set org.gnome.desktop.background picture-uri file://"$WALLPAPER"
}

set_cinnamon() {
  # used for Cinnamon 1.9.1
  # options: centered, none, scaled, spanned, stretched, wallpaper, zoom
  gsettings set org.cinnamon.background picture-options 'scaled'

  # change "set"  to "get" and delete option to return current background image
  gsettings set org.cinnamon.background picture-uri file://"$WALLPAPER"
}

set_cinnamon2() {
  # used for Cinnamon 2.0
  # options: centered, none, scaled, spanned, stretched, wallpaper, zoom
  gsettings set org.gnome.desktop.background picture-options 'scaled'

  # change "set"  to "get" and delete option to return current background image
  gsettings set org.gnome.desktop.background picture-uri file://"$WALLPAPER"
}

set_mate14() {
  mateconftool-2 -t str --set /desktop/mate/background/picture_filename "$WALLPAPER"

  # options; "none", "wallpaper" (tiled), "centered", "scaled", "stretched"
  mateconftool-2 -t str --set /desktop/mate/background/picture_options "scaled"
}

set_mate() {
  # options: centered, none, scaled, spanned, stretched, wallpaper, zoom
  gsettings set org.mate.background picture-options 'scaled'

  # change "set"  to "get" and delete option to return current background image
  gsettings set org.mate.background picture-filename "$WALLPAPER"
}

set_xfce() {
  # set STYLE to one fo the following numbers
  # 0 - Auto, 1 - Centered, 2 - Tiled, 3 - Stretched, 4 - Scaled, 5 - Zoomed
  # STYLE="4"
  # xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/image-style -s "$STYLE"
  xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/image-path -s "$WALLPAPER"
}

# randomize wallpaper list and select one image.  The purpose of the script.
random_sort() {
  WALLPAPER=$(find "$BGDIR" -type f -iregex ".*\.\(jpg\|png\|jpeg\)$" \
  | sort --random-sort | head --lines=1)
  2> /dev/null
}

lockscreen_random_sort() {
  LOCKSCREEN=$(find "$LOCKDIR" -type f -iregex ".*\.\(jpg\|png\|jpeg\)$" \
  | sort --random-sort | head --lines=1)
  2> /dev/null
}

# LOOP WALLPAPER
loop() {
  kill_loop() {
    # escape infinite loop by left-clicking tray notification icon
    loopID=$!
    yad --notification --image="preferences-desktop-wallpaper" \
    --text="Left click stopss rWall's slideshow. Middle-click closes tray icon" \
    --command="kill $loopID" --listen
    exit
  }

  # loop parameter requester
  loopForm=($(yad --form --title="Background Slideshow!" --separator=" " \
    --borders=3 --width=400 --height=100                                 \
    --field="Intervals"':NUM' '0!0..50!1'                                \
    --field="Speed in Seconds"':NUM' '20!0..3600!1'                      \
    --field="Pick Image Directory":DIR))
  # form array elements assigned for clarity
  INTERVAL=${loopForm[0]%.*}
  SPEED=${loopForm[1]%.*}
  LOOPDIR=${loopForm[2]}
  # determine image directory
  if [[ $LOOPDIR == "/" ]]; then
    if [[ -d "$2" ]]; then
      BGDIR="$2"
    else
      BGDIR="$USERDIR"
    fi
  else
    BGDIR="${loopForm[2]}"
  fi
  echo
  
  # default background swap speed
  if [[ -z $SPEED ]]; then
    $SPEED=10
  fi
  # starts infinite looping background if INTERVAL nill or zero
  if [[ -z $INTERVAL || $INTERVAL == 0 ]]; then
    echo " Press Ctrl+C to cancel the loop."
    echo
    while [[ true ]]; do
      random_sort
      $SETWALL
      sleep $SPEED
    done & #places loop in background, giving it a PID killable by the script
    kill_loop
    exit
  else
    echo " You have chosen to loop the background $INTERVAL times."
    echo " Press Ctrl+C to cancel the loop, or wait for the count to reach 0."
    echo " You can also left-click rWall's notification icon."
    echo
    echo " $(($INTERVAL - 1)) changes left."; echo
    while [[ $INTERVAL > 0 ]]; do
      random_sort
      $SETWALL
      sleep $SPEED
      let --INTERVAL
      if [[ $INTERVAL > 1 ]]; then
        echo " $(($INTERVAL - 1)) changes left."; echo
      elif [[ $INTERVAL == 1 ]]; then
        echo " Last change complete."; echo
      else
        echo " Goodbye."; echo; exit 0
      fi
    done &
    kill_loop
  fi
}

cd /

# automatically set desktop environment function and variable for current user
if [[ $(w -sh | grep gnome-session | wc -l) == "1" ]]; then
  if [[ $(cinnamon --version) == "Cinnamon 1.9.1" ]]; then
    SETWALL=set_cinnamon
    ENV="cinnamon"
  elif [[ -x /usr/bin/gsettings ]]; then
    SETWALL=set_gnome3
    ENV="gnome3"
  fi
elif [[ $(w -sh | grep cinnamon-session | wc -l) == "1" ]]; then
    SETWALL=set_cinnamon2
    ENV="cinnamon2"
elif [[ $(w -sh | grep gnome-session | wc -l) == "1" ]]; then
  if [[ -x /usr/bin/gconftool-2 ]]; then
    SETWALL=set_gnome2
    ENV="gnome2"
  fi
elif [[ $(xprop -root _DT_SAVE_MODE | grep xfce4 | wc -l) == "1" ]]; then  
  SETWALL=set_xfce
  ENV="xfce"
elif [[ $(w -sh | grep mate | wc -l) == "1" ]]; then
  if [[ -x /usr/bin/mateconftool-2 ]]; then
    SETWALL=set_mate14
    ENV="mate14"
  elif [[ -x /usr/bin/gsettings ]]; then
    SETWALL=set_mate
    ENV="mate"
  fi
elif [[ $(w -sh | grep kdeinit | wc -l) == "1" ]]; then
  SETWALL=set_kde
  ENV="kde"
elif [[ -x /usr/bin/feh ]]; then
  # feh can be used for many environments, so we set variable to "other"
  SETWALL=set_openbox
  ENV="other"
else
  echo "Missing components!  Please ensure GNOME, KDE, XFCE, or feh is installed."
fi

# establish image directory, includes provision for accepting options for $1
if [[ -d "$2" ]]; then
    BGDIR="$2"
elif [[ -d "$1" ]]; then
    BGDIR="$1"
else
    BGDIR="$USERDIR"
fi

random_sort

# OPTIONS
if [[ -d $2 || -z $2 ]]; then
  case $1 in
    "--help"               ) usage;;
    "--version" | "-v"     ) echo "$VERSION";;
    "--directory1" | "-d1" ) set_directory1 ; random_sort ; $SETWALL;;
    "--directory2" | "-d2" ) set_directory2 ; random_sort ; $SETWALL;;
    "--directory3" | "-d3" ) set_directory3 ; random_sort ; $SETWALL;;
    "--dir-dialog" | "-dd" ) call_dir_dialog ; random_sort ; $SETWALL;;
    "--file-dialog" | "-fd") call_file_dialog ; random_sort ; $SETWALL;;
    "--zen-dialog" | "-zd" ) call_zenity_dialog ; random_sort ; $SETWALL;;
    ""                     ) $SETWALL;;
    "$BGDIR"               ) $SETWALL;;
    "--loop" | "-l"        ) loop;;
    "--redpill"            ) echo "Why oh why didn't I take the BLUE pill?";;
    "--bluepill"           ) echo "Never send a human to do a machine's job.";;
    *                      ) echo "\"$1\" is invalid. Type \"rwall --help.\""
  esac
fi

exit 0
Last edited by LockBot on Wed Dec 28, 2022 7:16 am, edited 12 times in total.
Reason: Topic automatically closed 6 months after creation. New replies are no longer allowed.
KroniK907

Re: rWall, a Random Wallpaper Script

Post by KroniK907 »

I wish this worked with the fedora/cinnamon combo. gsettings doesn't seem to work any more with cinnamon 1.8. I cant seem to find where else to set the desktop background. The only way I found to change it now is through the settings window, which is a pain.
rockhazard
Level 1
Level 1
Posts: 43
Joined: Wed May 04, 2011 1:44 pm

Re: rWall, a Random Wallpaper Script

Post by rockhazard »

KroniK907, I have reproduced the problem in a Fedora 19 VM. I don't yet know the reasons behind it, but it appears the gsettings application will set any filename (even a fake one) as the wallpaper, and as you said it will not change the background. I'll have to do some digging around. The version of Cinnamon in my install was actually 1.9, but my personal install is 1.8.8, under LinuxMint, which works fine. One of my worries is that when Clem moves away from GNOME he will kill off cli access to background tools (as happened in KDE after v3.5). Hopefully this is a bug and not a bad omen.
rockhazard
Level 1
Level 1
Posts: 43
Joined: Wed May 04, 2011 1:44 pm

Re: rWall, a Random Wallpaper Script

Post by rockhazard »

I found the solution for Cinnamon 1.9.1 and also added support for XFCE. I tested it in Fedora 19 and it works. Have fun!
rockhazard
Level 1
Level 1
Posts: 43
Joined: Wed May 04, 2011 1:44 pm

Re: rWall, a Random Wallpaper Script

Post by rockhazard »

Updated instructions for KDE 4.13, and ensured compatibility with Cinnamon 2.2.
Sh0cK

Re: rWall, a Random Wallpaper Script

Post by Sh0cK »

Thank you for sharing rockhazard, I however can't get it to work, and reading through the file, I've got the impression that it can do quite a lot.
Can you maybe write down some instructions about how to get it to work on Linux Mint XFCE?
And will it change the wallpaper automatically with a predefined variable or can I make a button, that when pressed changed the wallpaper etc?

Thanks in advance!
Locked

Return to “Scripts & Bash”