Ubuntu – Change wallpaper by current time

customizationscriptswallpaper

While customizing my Ubuntu I thought to have two wallpapers, one for the day/afternoon and one for evening/night.

Is it possible to change the wallpaper basing myself to the current time? If so, how can I?

Thanks in advance.

Best Answer

Change wallpapers according day & night as simple as it gets

Assuming the night begins somewhere after 12:00 am and ends after midnight 24:00, usage of the script below is as simple as it gets:

  • Run it in the background with the command:

    python3 <script> <begin_of_evening> <end_of_night>
    

    for example:

    python3 /path/to/wallpaper_shift.py 19:00 6:00
    
  • During the day shift, set the wallpaper as you like. The script remembers your choice on the next day shift.

  • Likewise, during night shift, set your preferred wallpaper for the night. Again, the script remembers.

That's all. Now the wallpaper will switch according the moments of the day you set, running the script.

If the script is stopped

The script remembers the set wallpapers in a hidden file: ~/.wallset. WHen the script is (re-) started, it first tries to read the set wallpapers from the file. if it does not exist, it creates a new file, using the currently set wallpaper for both day- and night shift, until you change either one (or both).

Processor load zero

When the script is started, it calculates:

  • the current time of the day
  • the time span of night- and day shift
  • the time span from the current time of the day until the first switch
  • the current term (either day or night)

After that, between the wallpaper switches, the script only sleeps

what the script does

enter image description here

The script

#!/usr/bin/env python3
import subprocess
import os
import sys
import time

def write_walls(prefsfile, walls):
    # write new set of wallpapers to prefsfile
    open(prefsfile, "wt").write(("\n").join(walls))

def set_wall(wall):
    # set the wallapaper
    new = wall.replace("night:", "").replace("day:", "")
    command = "gsettings set org.gnome.desktop.background picture-uri "+\
              new
    subprocess.Popen(["/bin/bash", "-c", command])

def get_currwal():
    # get the current wallpaper
    return subprocess.check_output([
        "/bin/bash", "-c",
        "gsettings get org.gnome.desktop.background picture-uri"
        ]).decode("utf-8").strip()

def produce_setwalls(prefsfile):
    # on startup of the script, try to read the set wallapapers
    # or take the currently set on first run
    try:
        return open(prefsfile).read().splitlines()
    except FileNotFoundError:
        currwall = get_currwal()
        newwalls = ["night:"+currwall, "day:"+currwall]
        write_walls(prefsfile, newwalls)
        return newwalls

def convert_tosecs(t):
    # convert time of the day (hrs/mins) to seconds
    t = [int(n) for n in t.split(":")]
    return (3600*t[0])+(60*t[1])

# --- set constants
day_period = 24*3600
prefsfile = os.environ["HOME"]+"/.wallset"
# ---

# --- define time- shifts
curr_t = convert_tosecs(time.strftime("%H:%M"))
t1 = convert_tosecs(sys.argv[1])
t2 = convert_tosecs(sys.argv[2])
# ---

# --- define start- data
if any([curr_t > t1, curr_t < t2]):
    curr_term = "night"
    first_period = 86400 - curr_t + t2
else: 
    curr_term = "day"
    first_period = t1 - curr_t
# ---

# --- define time spans
night_shift = 86400 - t1 + t2
day_shift = 86400 - night_shift
# ---

# run first term, set wallpaper according (possible) settings
set_wallpapers = produce_setwalls(prefsfile)
to_set = [wall for wall in set_wallpapers if curr_term in wall][0]
set_wall(to_set)
time.sleep(first_period)

# then start loop
while True:
    if curr_term == "day":
        new_daywall = "day:"+get_currwal()
        sleeptime = night_shift
        new_term = "night"
    elif curr_term == "night":
        new_daywall = "night:"+get_currwal()
        sleeptime = day_shift
        new_term = "day"

    toremove = [item for item in set_wallpapers if curr_term+":" in item][0]
    # replace possibly changed wallpaper in the prefsfile and the currently
    # used set of wallpapers
    set_wallpapers.remove(toremove)
    set_wallpapers.append(new_daywall)
    write_walls(prefsfile, set_wallpapers)
    # switch daytime <> night, set the wallpaper accordingly
    curr_term = new_term
    set_wall([item for item in set_wallpapers if new_term+":" in item][0])
    # sleep again...
    time.sleep(sleeptime)

How to use

  1. Copy the script into an empty file, save it as wallpaper_shift.py
  2. Test- run it from a terminal by the command (example):

    python3 /path/to/wallpaper_shift.py 19:00 6:00
    

    where the time format should be 20:00

  3. In any of the two terms, simply set the wallpaper as you like, the script remembers and re- applies it on the next "day" or "night".
  4. If all works fine, add it to Startup Applications: Dash > Startup Applications > Add. Add the command:

    /bin/bash -c "sleep 20 && python3 /path/to/wallpaper_shift.py 19:00 6:00"
    

Notes

  1. The script works correctly if the evening starts between 12:00 a.m. and ends after midnight. That seems however obvious.
  2. The script rounds the time on minutes, meaning that the accuracy is also somewhere between 0-60 seconds.