3 import commands
, sys
, os
, os
.path
, subprocess
, time
4 from GregDebug
import debug
, setDebugLevel
, DEBUG_LEVEL_DEBUG
, DEBUG_LEVEL_LOW
, DEBUG_LEVEL_MEDIUM
, DEBUG_LEVEL_HIGH
, DEBUG_INCREMENT
6 import python24_adapter
# NB: Must be imported before collections
9 """This is a cross platform/cross window manager way to change your current
12 __all__
= ('RandomBG')
14 KDE_CONFIG
= os
.path
.expanduser('~/.kde/share/config/kdesktoprc')
16 def RandomBG(*args
, **kwargs
):
17 """Desktop Changer factory"""
21 debug("Testing for OSX (NonX11)", DEBUG_LEVEL_LOW
)
22 if commands
.getstatusoutput("ps ax -o command -c|grep -q WindowServer")[0] == 0:
23 ret
= __OSXChanger(*args
, **kwargs
)
25 if 'DISPLAY' not in os
.environ
or os
.environ
['DISPLAY'].startswith('/tmp/launch'):
29 if os
.uname()[0] == 'Darwin':
30 # Try to detect if the X11 server is running on OSX
31 if commands
.getstatusoutput("ps ax -o command|grep -q '/.*X11 .* %s'" % os
.environ
['DISPLAY'])[0] != 0:
32 # X11 is not running for this display
35 debug("Testing for KDE", DEBUG_LEVEL_LOW
)
36 if commands
.getstatusoutput("xwininfo -name 'KDE Desktop'")[0] == 0:
38 ret
.nextChanger
= __KDEChanger(*args
, **kwargs
)
40 ret
= __KDEChanger(*args
, **kwargs
)
42 debug("Testing for WMaker", DEBUG_LEVEL_LOW
)
43 if commands
.getstatusoutput("xlsclients | grep -qi wmaker")[0] == 0:
45 ret
.nextChanger
= __WMakerChanger(*args
, **kwargs
)
47 ret
= __WMakerChanger(*args
, **kwargs
)
50 raise Exception("Unknown window manager")
54 class __BaseChanger(object):
55 def __init__(self
, filelist
, backgroundColour
='black', permanent
=False):
56 debug('Determined the window manager is "%s"' % self
.__class
__.__name
__, DEBUG_LEVEL_MEDIUM
)
57 self
.backgroundColour
= backgroundColour
58 self
.permanent
= permanent
59 self
.filelist
= filelist
60 # Used to 'chain' background changers
61 self
.nextChanger
= None
63 def callChained(self
, filename
):
64 if self
.nextChanger
is None:
67 return self
.nextChanger
.changeTo(filename
)
70 file = self
.filelist
.getNextRandomImage()
71 return self
.changeTo(file) and self
.callChained(file)
74 file = self
.filelist
.getPrevRandomImage()
75 return self
.changeTo(file) and self
.callChained(file)
77 def cycleReload(self
):
78 file = self
.filelist
.getCurrentImage()
79 return self
.changeTo(file) and self
.callChained(file)
82 class __WMakerChanger(__BaseChanger
):
83 _ConvertedWallpaperLocation
= '/tmp/wallpapers_wmaker/'
84 def _removeOldImageCache(self
):
85 """Cleans up any old temp images"""
86 if not os
.path
.isdir(self
._ConvertedWallpaperLocation
):
87 os
.mkdir(self
._ConvertedWallpaperLocation
)
88 for fullpath
, filenames
, dirnames
in os
.walk(self
._ConvertedWallpaperLocation
, topdown
=False):
89 for filename
in filenames
:
90 os
.unlink(os
.path
.join(fullpath
, filename
))
91 for dirname
in dirnames
:
92 os
.unlink(os
.path
.join(fullpath
, dirname
))
94 def _convertImageFormat(self
, file):
95 """Convert the image to a png, and store it in a local place"""
96 self
._removeOldImageCache
()
97 output_name
= os
.path
.join(self
._ConvertedWallpaperLocation
, '%s.png' % time
.time())
98 cmd
= ["convert", '-resize', '1280', '-gravity', 'Center', '-crop', '1280x800+0+0', file, output_name
]
99 debug("""Convert command: '"%s"'""" % '" "'.join(cmd
), DEBUG_LEVEL_DEBUG
)
100 return output_name
, subprocess
.Popen(cmd
, stdout
=sys
.stdout
, stderr
=sys
.stderr
, stdin
=None).wait()
101 def changeTo(self
, file):
102 file, convert_status
= self
._convertImageFormat
(file)
104 debug('Convert failed')
106 "-b", self
.backgroundColour
, # Sets the background colour to be what the user specified
107 "-S", # 'Smooth' (WTF?)
108 "-e", # Center the image on the screen (only affects when the image in no the in the correct aspect ratio
109 ### "-a", # scale the image, keeping the aspect ratio
110 "-u", # Force this to be the default background
114 cmd
+= ["-u"] # update the wmaker database
116 debug('''WMaker bgset command: "'%s'"''' % "' '".join(cmd
), DEBUG_LEVEL_DEBUG
)
117 return not subprocess
.Popen(cmd
, stdout
=sys
.stdout
, stderr
=sys
.stderr
, stdin
=None).wait()
119 class __OSXChanger(__BaseChanger
):
120 _ConvertedWallpaperLocation
= '/tmp/wallpapers/'
121 def _removeOldImageCache(self
):
122 """Cleans up any old temp images"""
123 if not os
.path
.isdir(self
._ConvertedWallpaperLocation
):
124 os
.mkdir(self
._ConvertedWallpaperLocation
)
125 for fullpath
, filenames
, dirnames
in os
.walk(self
._ConvertedWallpaperLocation
, topdown
=False):
126 for filename
in filenames
:
127 os
.unlink(os
.path
.join(fullpath
, filename
))
128 for dirname
in dirnames
:
129 os
.unlink(os
.path
.join(fullpath
, dirname
))
131 def _convertImageFormat(self
, file):
132 """Convert the image to a png, and store it in a local place"""
133 self
._removeOldImageCache
()
134 output_name
= os
.path
.join(self
._ConvertedWallpaperLocation
, '%s.png' % time
.time())
135 cmd
= ["convert", file, output_name
]
136 debug("""Convert command: '"%s"'""" % '" "'.join(cmd
), DEBUG_LEVEL_DEBUG
)
137 return output_name
, subprocess
.Popen(cmd
, stdout
=sys
.stdout
, stderr
=sys
.stderr
, stdin
=None).wait()
139 def changeTo(self
, file):
140 output_name
, ret
= self
._convertImageFormat
(file)
141 if ret
: # Since 0 indicates success
142 debug("Convert failed %s" % ret
)
144 cmd
= """osascript -e 'tell application "finder" to set desktop picture to posix file "%s"'""" % output_name
145 debug(cmd
, DEBUG_LEVEL_DEBUG
)
146 return not commands
.getstatusoutput(cmd
)[0]
148 class __KDEChanger(__BaseChanger
):
149 def _parseKDEConfig(self
, filename
= KDE_CONFIG
):
150 fd
= open(filename
, 'r')
151 result
= collection
.defaultdict(dict)
155 if not line
or line
.startswith('#'):
158 if line
.startswith('[') and line
.endswith(']'):
163 raise Exception('Invalid kdesktoprc file')
165 unpack
= line
.split('=', 1)
169 key
, val
= unpack
[0], None
170 result
[section
][key
] = val
175 def _writeKDEConfig(self
, config
, filename
= KDE_CONFIG
):
176 fd
= open(filename
, 'w')
177 for section
, values
in config
.items():
178 print >>fd
, '[%s]' % section
179 for k
, v
in values
.items():
181 print >>fd
, '%s=%s' % (k
,v
)
187 def changeTo(self
, file):
188 kdeconfig
= self
._parseKDEConfig
()
189 #kdeconfig['Background Common']['DrawBackgroundPerScreen_0']='true'
190 for section
in ('Desktop0', 'Desktop0Screen0'):
191 kdeconfig
[section
]['Wallpaper'] = file
192 kdeconfig
[section
]['UseSHM'] = 'true'
193 kdeconfig
[section
]['WallpaperMode'] = 'ScaleAndCrop'
194 # Ensure that random mode is disabled...
195 if 'MultiWallpaperMode' in kdeconfig
[section
]:
196 del kdeconfig
[section
]['MultiWallpaperMode']
198 self
._writeKDEConfig
(kdeconfig
)
200 return not subprocess
.Popen(['dcop', 'kdesktop', 'KBackgroundIface', 'configure'],
201 stdout
=sys
.stdout
, stderr
=sys
.stderr
, stdin
=open('/dev/null', 'r')).wait()