]> code.delx.au - bg-scripts/blobdiff - wallchanger.py
Added support for Unity
[bg-scripts] / wallchanger.py
index 6c2ba004c3b14ad0a69b5909c62b7242c899c6ce..4ee3b08f9c5cccf6989ee8e80ab235bf1d2b9483 100755 (executable)
@@ -6,6 +6,10 @@
 
 import commands, sys, os, os.path, time
 import logging
+try:
+       import PIL, PIL.Image
+except ImportError:
+       PIL = None
 
 __all__ = ("init", "set_image")
 
@@ -21,6 +25,10 @@ def set_image(filename):
 def init(*args, **kwargs):
        """Desktop Changer factory"""
 
+       if sys.platform == "win32":
+               changers.append(WIN32Changer(*args, **kwargs))
+               return
+
        logging.debug("Testing for OSX (NonX11)")
        if commands.getstatusoutput("ps ax -o command -c|grep -q WindowServer")[0] == 0:
                changers.append(OSXChanger(*args, **kwargs))
@@ -39,8 +47,12 @@ def init(*args, **kwargs):
        if commands.getstatusoutput("xwininfo -name 'KDE Desktop'")[0] == 0:
                changers.append(KDEChanger(*args, **kwargs))
 
+       logging.debug("Testing for Unity")
+       if commands.getstatusoutput("xlsclients | grep -qi unity")[0] == 0:
+               changers.append(UnityChanger(*args, **kwargs))
+
        logging.debug("Testing for Gnome")
-       if commands.getstatusoutput("xwininfo -name 'gnome-session'")[0] == 0:
+       if commands.getstatusoutput("xwininfo -name 'gnome-settings-daemon'")[0] == 0:
                changers.append(GnomeChanger(*args, **kwargs))
 
        logging.debug("Testing for WMaker")
@@ -78,6 +90,27 @@ class BaseChanger(object):
        def set_image(self, filename):
                raise NotImplementedError()
 
+       def convert_image_format(self, filename, format='BMP', allowAlpha=False, extension='.bmp'):
+               """Convert the image to another format, and store it in a local place"""
+               if not os.path.exists(filename):
+                       logger.warn('The input file "%s" does not exist, so it will not be converted', filename)
+                       return filename, False
+               if PIL is None:
+                       logger.warn('PIL could not be found, not converting image format')
+                       return filename, False
+
+               self.remove_old_image_cache()
+               output_name = os.path.join(self._ConvertedWallpaperLocation, '%s%s' % (time.time(), extension))
+               img = PIL.Image.open(filename)
+
+               # Remove the alpha channel if the user doens't want it
+               if not allowAlpha and img.mode == 'RGBA':
+                       img = img.convert('RGB')
+               img.save(output_name, format)
+
+               return output_name, True
+
+
 class WMakerChanger(BaseChanger):
        name = "WindowMaker"
        _ConvertedWallpaperLocation = '/tmp/wallpapers_wmaker/'
@@ -141,10 +174,7 @@ class OSXChanger(BaseChanger):
                self.remove_old_image_cache()
                output_name = os.path.join(self._ConvertedWallpaperLocation, '%s.png' % time.time())
                try:
-                       import PIL, PIL.Image
-                       img = PIL.Image.open(file)
-                       img.save(output_name, "PNG")
-                       return output_name, True
+                       return super(OSXChanger, self).convert_image_format(file, format='PNG', extension='.png')
                except ImportError:
                        logging.debug('Could not load PIL, going to try just copying the image')
                        import shutil
@@ -178,6 +208,49 @@ class OSXChanger(BaseChanger):
                logging.debug(cmd)
                return not commands.getstatusoutput(cmd)[0]
 
+class WIN32Changer(BaseChanger):
+       name = "Windows"
+       _ConvertedWallpaperLocation = os.path.join(os.environ.get('APPDATA', os.path.expanduser('~')), 'wallchanger')
+
+       def __init__(self, *args, **kwargs):
+               BaseChanger.__init__(self, *args, **kwargs)
+               if not self.convert:
+                       logging.warn('Running on windows, but convert is not set')
+
+       def remove_old_image_cache(self):
+               """Cleans up any old temp images"""
+               if not os.path.isdir(self._ConvertedWallpaperLocation):
+                       os.mkdir(self._ConvertedWallpaperLocation)
+               for fullpath, filenames, dirnames in os.walk(self._ConvertedWallpaperLocation, topdown=False):
+                       for filename in filenames:
+                               os.unlink(os.path.join(fullpath, filename))
+                       for dirname in dirnames:
+                               os.unlink(os.path.join(fullpath, dirname))
+
+       def set_image(self, filename):
+               import ctypes
+               user32 = ctypes.windll.user32
+
+               # Taken from the Platform SDK
+               SPI_SETDESKWALLPAPER = 20
+               SPIF_SENDWININICHANGE = 2
+
+               if self.convert:
+                       filename, ret = self.convert_image_format(filename)
+                       if not ret:
+                               logging.debug("Convert failed")
+                               return False
+
+               # Parameters for SystemParametersInfoA are:
+               # (UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
+               user32.SystemParametersInfoA(
+                       SPI_SETDESKWALLPAPER,
+                       0,
+                       filename,
+                       SPIF_SENDWININICHANGE,
+               )
+               return True
+
 class GnomeChanger(BaseChanger):
        name = "Gnome"
        def set_image(self, file):
@@ -185,6 +258,13 @@ class GnomeChanger(BaseChanger):
                logging.debug(cmd)
                return not self._runProgram(cmd)
 
+class UnityChanger(BaseChanger):
+       name = "Unity"
+       def set_image(self, file):
+               cmd = ['gsettings', 'set', 'org.gnome.desktop.background', 'picture-uri', 'file://'+file]
+               logging.debug(cmd)
+               return not self._runProgram(cmd)
+
 class KDEChanger(BaseChanger):
        name = "KDE"
        def set_image(self, file):