Algorithm to change ubuntu desktop wallpaper

Solution 1:

What changes the wallpaper

In case of Ubuntu's default behavior when it comes to backgrounds, that's set through gsettings. In a nut shell, it's a form of database for settings to various apps. The simple command is this:

gsettings set org.gnome.desktop.background picture-uri "$FILE" 

, where "$FILE" is the shell script variable that holds full path to image in the form file:///path/to/image.png

That's somewhat different from other desktop environments. Think of Ubuntu's Unity and Gnome as having a layer above typical X11 server ( i.e. the layer above GUI environment ). In such environments as blackbox or openbox you'd need to call an external program. For instance , feh --bg-scale /path/to/image

I assume you want to deal with default environment - Ubuntu's Unity.

Making a shell function

Here's example of what I use in my .bashrc file.

function chbackground {
    FILE="'file://$(readlink -f "$1" )'" 
    echo changing to "$FILE" 
    gsettings set org.gnome.desktop.background picture-uri "$FILE" 
}

The function can be called like so

chbackground WALLPAPERS-FOLDER/cool-background.png

This function has two important parts. First, we can either have full path or partial path to the file - that's what readlink -f "$1" takes care of - it returns full path to image. Then we turn that into a string by combining output of readlink -f "$1" and file://. Remember, Unix path is always starting with root folder, /, so we need only leading two slashes there. Result would be file:///home/user/WALLPAPERS-FOLDER/cool-background.png string and stored in FILE variable.

Finally we call gsettings with FILE as argument.

This function can be part of any script and called with any partial or full path as parameter

Putting together a script

Here's a script I sketched out in about 15 minutes that will make a list of images , and then select random image out of that list, and set background to that image. The script is also placed in my github , sergrep repository repository and will be developed just a little bit more to include extra functionality, but for the most part , the code version here does the big job.

In order to automate this script , refer to How do i make a program autostart every time i log in ?

#!/usr/bin/env bash
#
###########################################################
# Author: Serg Kolo , contact: [email protected] 
# Date: March 10th 2016 
# Purpose: Set random wallpaper
#      To make it start automatically, add it as one of 
#          the Startup Applications in Ubuntu's Unity 
#          or Gnome 
# 
# Written for: https://askubuntu.com/q/744464/295286
# Tested on: Ubuntu 14.04 LTS
###########################################################
# Copyright: Serg Kolo , 2016
#    
#     Permission to use, copy, modify, and distribute this software is hereby granted
#     without fee, provided that  the copyright notice above and this permission statement
#     appear in all copies.
#
#     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
#     THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
#     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
#     DEALINGS IN THE SOFTWARE.

ARGV0="$0"
ARGC=$#
change_background()
{
    FILE="'file://$(readlink -f "$1" )'" 
    echo changing to "$FILE" 
    gsettings set org.gnome.desktop.background picture-uri "$FILE"
}

make_list()
{
  # -max-depth may be optional , if you want to 
  # traverse subdirectories,too
  find "$1" -maxdepth 1 -type f > "$2"
}

main()
{
  # Variables
  local DISPLAY=:0 # ensure this is set
  local DIR="$1"
  local LIST="/tmp/wallpaper.list"
  local TIME="$2"
  # cat $LIST # for debugging only
  make_list "$DIR" "$LIST"
  while true 
  do
     change_background $( shuf $LIST | head -n 1   )
     sleep "$TIME"      
  done
}

main "$@"