#!/usr/bin/env python
#
# bg_slideshow.py
# (c) 2012 MB http://somethingididnotknow.wordpress.com
#
# This script is released under WTFPL, but it's heavily inspired from Romano
# Giannetti's original bg_slideshow.py
# See http://rlog.rgtti.com/software/linux/wallpaper-slideshow-for-gnome3/
#
# A simple wallpaper changer for GNOME desktop.
# List your wallpapers folders in file ~/.bg_slideshow.conf and run the script:
#
# python bg_slideshow.py &
#
# or add a startup entry using gnome-session-properties
import sys
import os
import random
from time import gmtime, sleep, strftime
class WallpaperChanger:
# conf file is in ~/.bg_slideshow.conf change it here if you want
conf_file = os.path.join(os.getenv("HOME"), '.bg_slideshow.conf')
mode = "zoom" # one of none, centered, wallpaper, scaled, stretched, zoom, spanned
delay = 3 * 60 # in seconds
formats = [".jpg", ".png", ".gif", ".jpeg"] # accepted formats
files = []
all_files = set()
def __init__(self):
self.index = 0
self.parse_conf()
def parse_conf(self):
"""parses the configuration file, interpreting every non-commented line
as a directory into which wallpaper images reside.
In case no images are found, the script exits"""
self.bad_folders = []
if not os.path.isfile(self.conf_file):
with open(self.conf_file, 'w') as conf:
self.append_error(conf, 'List your wallpapers folder here')
print 'List your wallpapers folders in configuration file ', self.conf_file
sys.exit(1)
self.conf_last_modified = os.path.getmtime(self.conf_file)
self.files = self.get_all_files()
if not self.files:
self.append_error(conf, 'No images found!')
sys.exit(1)
self.all_files = set(self.files)
random.shuffle(self.files)
def get_all_files(self):
"""adds all files in all directories found in the configuration file to
a list containing all wallpapers to be shown with no duplicates (based
on complete file name)"""
files = []
with open(self.conf_file, 'r+') as conf:
# trim whitespaces and newlines
for line in [x.strip() for x in conf.readlines()]:
if not line.startswith('#'):
if os.path.isdir(line):
try:
files.extend([os.path.join(line, file) for file in os.listdir(line) if os.path.splitext(file)[1] in self.formats])
except OSError, e:
# deal with bad folders later...
self.bad_folders.append('%s: %s' % (line, e.strerror))
if self.bad_folders:
for folder in self.bad_folders:
self.append_error(conf, folder)
return self.remove_duplicates(files)
def remove_duplicates(self, files):
seen = set()
seen_add = seen.add
return [x for x in files if x not in seen and not seen.add(x)]
def append_error(self, conf, line):
# go to the end of conf file and append messages there
conf.seek(0, 2)
conf.write('# %s - %s%s' % (strftime("%Y-%m-%d %H:%M:%S", gmtime()), line, os.linesep))
def poll_for_new_files(self):
"""checks whether new files have been added to the configured folders"""
all_files = set(self.get_all_files())
new_files = all_files - self.all_files
if new_files:
shown = set(self.files[:self.index])
self.files = list(all_files - shown)
self.all_files = all_files
random.shuffle(self.files)
self.index = 0
def run(self):
sleep(self.delay) # this seems to be needed to avoid gnome-shell crashes
while True:
last_edit = os.path.getmtime(self.conf_file)
if last_edit != self.conf_last_modified:
self.parse_conf()
next_bg = self.files[self.index]
if os.path.isfile(next_bg):
os.system('/usr/bin/gsettings set org.gnome.desktop.background picture-uri file://%s' % self.files[self.index])
os.system('/usr/bin/gsettings set org.gnome.desktop.background picture-options %s' % self.mode)
sleep(self.delay)
self.index += 1
self.poll_for_new_files()
if self.index >= len(self.files):
self.index = 0
self.parse_conf() # this also checks that at least a bg exists!
random.shuffle(self.files)
if __name__ == "__main__":
changer = WallpaperChanger()
changer.run()