X-Git-Url: https://code.delx.au/bg-scripts/blobdiff_plain/de8ac8c2cc2d21dc2e649ca3e565ee3907f1038a..fa352f275fdc2e7ebbb24d4c4d23a8665688b819:/bin/randombg.py diff --git a/bin/randombg.py b/bin/randombg.py new file mode 100755 index 0000000..7a94fc0 --- /dev/null +++ b/bin/randombg.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python + +import sys, os, os.path, socket +from optparse import OptionParser, Values + +VERSION = "1.1" +CACHE_LOCATION = os.path.expanduser('~/.randombg2_filelist_cache') +SOCKET_FILE = os.path.expanduser('~/tmp/tmp_socket') + +try: + # These are my libraries... + import GregDebug, AsyncSocket, WallChanger, SigHandler + + from GregDebug import debug, setDebugLevel, DEBUG_LEVEL_DEBUG, DEBUG_LEVEL_LOW, DEBUG_LEVEL_MEDIUM, DEBUG_LEVEL_HIGH, DEBUG_INCREMENT + + from FileLists import * +except ImportError, e: + print >>sys.stderr, "Missing libraries!\nExiting..." + sys.exit(1) + +def buildparser(): + def buildOptions(): + pass + def addfilestolist(optclass, opt, value, parser, fileList): + fo = open(value) + for line in fo: + fileList.list.append(line.strip()) + fo.close() + fileList.allowAllRandom = False + + parser = OptionParser(version="%prog " + VERSION, + description = "Picks a random background image", + usage = "%prog [options] dir [dir2 ...]") + parser.add_option("-p", "--permanent", + action="store_true", dest="permanent", default=False, + help="Make the background permanent. Note: This will cause all machines logged in with this account to simultaneously change background [Default: %default]") + parser.add_option("-q", "--quiet", "--silent", + action="count", dest="quiet", default=0, + help="Make the script quiet (good for running from a shell script)") + parser.add_option("-v", '-d', "--verbose", "--debug", + action="count", dest="verbose", default=0, + help="Make the louder (good for debugging, or those who are curious)") + parser.add_option("-b", "--background-colour", + action="store", type="string", dest="background_colour", default="black", + help="Change the default background colour that is displayed if the image is not in the correct aspect ratio [Default: %default]") + parser.add_option("--all-random", + action="store_true", dest="all_random", default=False, + help="Make sure that all images have been displayed before repeating an image") + parser.add_option("--folder-random", + action="store_true", dest="folder_random", default=False, + help="Give each folder an equal chance of having an image selected from it") + #parser.add_option("--file-list", + # action="callback", callback=addfilestolist, type="string", callback_args=(fileList,), + # help="Adds the list of images from the external file") + parser.add_option("--cycle", + action="store", type="int", default=0, dest="cycle_time", + help="Cause the image to cycle every X seconds") + return parser + + +def createIPCClient(domainSocketName): + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.connect(domainSocketName) + sock_file = sock.makefile() + return sock_file + +def main(): + if os.path.exists(SOCKET_FILE): + # We are the client + sock = createIPCClient(SOCKET_FILE) + print >>sock, "CMD NEXT" +### print >>sock, "CMD PREVIOUS" +### print >>sock, "CMD PAUSE" + sock.close() + else: + # We are the server + try: + Server(SOCKET_FILE)() + finally: + # Make sure that the socket is cleaned up + os.unlink(SOCKET_FILE) + +class Server(object): + def __init__(self, domainSocketName): + self.socketHandler = self._createIPCServer(domainSocketName) + self.callbackObj = None + + parser = buildparser() + useroptions, paths = parser.parse_args(sys.argv[1:]) + + setDebugLevel(DEBUG_INCREMENT * (useroptions.quiet - useroptions.verbose)) + debug("Just set GregDebug.DEBUG_LEVEL to %d" % GregDebug.DEBUG_LEVEL, DEBUG_LEVEL_LOW) + + self.filelist = self.__getFileList(useroptions, paths) + + if not self.filelist.hasImages(): + print >>sys.stderr, "No files!" + parser.print_help() + sys.exit(1) + + debug("Initilizing RandomBG", DEBUG_LEVEL_DEBUG) + self.randombg = WallChanger.RandomBG(self.filelist, useroptions.background_colour, useroptions.permanent) + + # Store some of the other useful options + self.cycle_time = useroptions.cycle_time + + def __getFileList(self, useroptions, paths): + if useroptions.all_random: + filelist = AllRandomFileList() + elif useroptions.folder_random: + filelist = FolderRandomFileList() + else: + filelist = RandomFileList() + + for path in paths: + filelist.doAddPath(path) + + if filelist.attemptCacheLoad(CACHE_LOCATION): + debug("Loaded cache successfully", DEBUG_LEVEL_LOW) + else: + debug("Could not load cache") + filelist.doScanPaths() + return filelist + + def cycle_reload(self): + debug("Reloading wallpaper", DEBUG_LEVEL_LOW) + ret = self.randombg.cycleReload() + if not ret: + debug('Could not set wallpaper. Returned "%s"' % ret) + debug('About to sleep for "%d" seconds' % self.cycle_time, DEBUG_LEVEL_LOW) + self.callbackObj = self.socketHandler.addCallback(self.cycle_time, self.cycle_next) + return ret + + def cycle_next(self): + debug("Cycling wallpaper", DEBUG_LEVEL_LOW) + ret = self.randombg.cycleNext() + if not ret: + debug('Could not set wallpaper. Returned "%s"' % ret) + debug('About to sleep for "%d" seconds' % self.cycle_time, DEBUG_LEVEL_LOW) + self.callbackObj = self.socketHandler.addCallback(self.cycle_time, self.cycle_next) + self.filelist.doStoreCache(CACHE_LOCATION) + return ret + + def cycle_prev(self): + debug("Cycling wallpaper", DEBUG_LEVEL_LOW) + ret = self.randombg.cyclePrev() + if not ret: + debug('Could not set wallpaper. Returned "%s"' % ret) + debug('About to sleep for "%d" seconds' % self.cycle_time, DEBUG_LEVEL_LOW) + # Yes this is ment to be cycle_next + self.callbackObj = self.socketHandler.addCallback(self.cycle_time, self.cycle_next) + self.filelist.doStoreCache(CACHE_LOCATION) + return ret + + def _finished(self): + self.filelist.doStoreCache(CACHE_LOCATION) + + def __call__(self): + # Callback immediatly + self.socketHandler.addCallback(0.0, self.cycle_reload) + # Now go into the main loop + self.socketHandler.mainLoop() + # Clean up time + self._finished() + + def _createIPCServer(self, domainSocketName): + """Create the Server socket, and start listening for clients""" + + class Handler(object): + def __init__(self, parent): + self.parent = parent + def _removeOldTimer(self): + if self.parent.callbackObj: + self.parent.socketHandler.removeCallback(self.parent.callbackObj) + def _cmd_PAUSE(self): + debug("Pausing randombg") + self._removeOldTimer() + def _cmd_NEXT(self): + self._removeOldTimer() + self.parent.cycle_next() + def _cmd_PREVIOUS(self): + self._removeOldTimer() + self.parent.cycle_prev() + def _cmd_RESCAN(self): + self.parent.filelist.doScanPaths() + self._cmd_NEXT() + def _cmd_RELOAD(self): + self._removeOldTimer() + self.parent.cycle_reload() + def _processLine(self, line): + prefix, cmd = line.split(None, 1) + if prefix != 'CMD': + debug('Unknown command received "%s"' % line) + return + if hasattr(self, '_cmd_%s' % cmd): + getattr(self, '_cmd_%s' % cmd)() + else: + debug('Unknown command received "%s"' % cmd) + def __call__(self, lineReader): + try: + while lineReader.hasLine(): + self._processLine(lineReader.readline()) + except Exception, e: + debug(str(e)) + + def handleClient(sock): + conn, address = sock.accept() + async_handler.addLineBufferedSocket(conn, Handler(self) ) + + async_handler = AsyncSocket.AsyncSocketOwner() + + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.bind(domainSocketName) + sock.listen(2) # Backlog = 2 + + async_handler.addSocket(sock, handleClient) + + return async_handler + +if __name__ == "__main__": + main()