]> git.phdru.name Git - xsetbg.git/blob - xsetbg.py
Fix(DB): Fix column encoding
[xsetbg.git] / xsetbg.py
1 """Set a random background image (XWin)
2
3 Select a random image from a (list of) directory(s)
4 and set it as the desktop wallpaper (display it in the root window)
5 using xli program.
6
7 """
8
9 from fcntl import flock, LOCK_EX, LOCK_UN, LOCK_NB
10 from datetime import timedelta
11 import os
12 import random
13 import re
14 import subprocess
15 import sys
16 from time import time
17
18 from xsetbg_conf import xsetbg_dir, xsetbg_conf
19 from xsetbg_db import xsetbg_db
20
21 __all__ = ['change']
22
23
24 def error(error_str):
25     sys.exit("%s: Error: %s\n" % (sys.argv[0], error_str))
26
27
28 if not xsetbg_db:
29     error("No database found. Run rescan_fs.py. Abort.")
30
31 if xsetbg_db.select().count() == 0:
32     error("No images found. Run rescan_fs.py. Abort.")
33
34
35 # minimum time in seconds between background image changes
36 if xsetbg_conf.has_option("xsetbg", "min_pause"):
37     min_pause = xsetbg_conf.getint("xsetbg", "min_pause")
38 else:
39     min_pause = 60
40
41 borders = xsetbg_conf.get("xsetbg", "borders").split(',')
42 if xsetbg_conf.has_option("xsetbg", "borders"):
43     borders = [border.strip() for border in
44                xsetbg_conf.get("xsetbg", "borders").split(',')]
45 else:
46     borders = ["darkcyan", "steelblue", "midnightblue"]
47
48 # minimum time in seconds between occurences of the same image
49 if xsetbg_conf.has_option("xsetbg", "min_delay"):
50     min_delay = xsetbg_conf.get("xsetbg", "min_delay")
51
52     # Borrowed from http://stackoverflow.com/a/2765366
53     td_re = re.compile('(?:(?P<years>\d+)y)?'
54                        '(?:(?P<months>\d+)m)?'
55                        '(?:(?P<days>\d+)d)?'
56                        '(?:T(?:(?P<hours>\d+)h)?'
57                        '(?:(?P<minutes>\d+)m)?(?:(?P<seconds>\d+)s)?)?')
58     td_dict = td_re.match(min_delay).groupdict(0)
59     delta = timedelta(days=int(td_dict['days']) +
60                       (int(td_dict['months']) * 30) +
61                       (int(td_dict['years']) * 365),
62                       hours=int(td_dict['hours']),
63                       minutes=int(td_dict['minutes']),
64                       seconds=int(td_dict['seconds']))
65
66     if delta:
67         min_delay = delta.days * 24*3600 + delta.seconds
68     else:
69         min_delay = int(min_delay)
70
71 else:
72     min_delay = 3600*24  # 24 hours
73
74
75 if xsetbg_db.select(
76         '(is_image = 1) AND (last_shown IS NULL OR last_shown < %d)' %
77         (time() - min_delay)).count() == 0:
78     error("No unshown images found. Run rescan_fs.py "
79           "or decrease min_delay. Abort.")
80
81 fs_encoding = xsetbg_conf.get("images", "fs_encoding")
82
83
84 def change(force=False):
85     # Use the program's file as the lock file:
86     # lock it to prevent two processes run in parallel.
87     lock_file = open(os.path.join(xsetbg_dir, 'xsetbg.py'), 'r')
88
89     try:
90         flock(lock_file, LOCK_EX | LOCK_NB)
91     except IOError:  # already locked
92         lock_file.close()
93         return
94
95     try:
96         timestamp = xsetbg_db.select(
97             '(is_image = 1) AND (last_shown IS NOT NULL)',
98             orderBy='-last_shown')[0].last_shown
99         current_time = time()
100
101         if not force and timestamp is not None and \
102                 current_time - timestamp < min_pause:
103             # Too early to change background
104             return
105
106         # Select a random image that has never been shown
107         not_shown_select = xsetbg_db.select(
108             '(is_image = 1) AND (last_shown IS NULL)')
109         not_shown_count = not_shown_select.count()
110         if not_shown_count:
111             row = not_shown_select[random.randint(0, not_shown_count - 1)]
112         else:
113             old_shown_select = xsetbg_db.select(
114                 '(is_image = 1) AND '
115                 '(last_shown IS NOT NULL AND last_shown < %d)' %
116                 current_time - min_delay)
117             old_shown_count = old_shown_select.count()
118             if old_shown_count:
119                 row = old_shown_select[random.randint(0, old_shown_count - 1)]
120             else:
121                 error("No images to show found. Run rescan_fs.py "
122                       "or decrease min_delay. Abort.")
123
124         program_options = ["xli", "-border", random.choice(borders),
125                            "-center", "-onroot", "-quiet", "-zoom", "auto",
126                            row.full_name.encode(fs_encoding)]
127
128         rc = subprocess.call(program_options)
129         if rc:
130             error("cannot execute xli!")
131         else:
132             row.last_shown = current_time
133
134     finally:
135         # Unlock and close the lock file
136         flock(lock_file, LOCK_UN)
137         lock_file.close()