Jump to content
Science Forums

Xrandsetroot rewritten in python


Recommended Posts

I've been working on this for a while, mainly because of one of my friends problems with xrandsetroot. Basically its a Perl script that is executed in the background by crontab every certain amount of time that you specify. What it did was read off all image files in a specified directory and then choose one of them randomly to set as a background. Now, if this sounds awesome, there are tradeoffs; it takes a considerable toll on the system once you have more than 100 files in the directory, especially noticed when you are compiling something...

 

Now a friend of mine got sick of xrandsetroot script and found a C file that reads off the directory from a text file you set up and chooses a random line to execute. Tradeoff here is that now that my friend has over a 1000 files in his folder, the C program takes time to read the file, parse it and choose a random value in the array to execute the bg switcher.

 

He was looking for a way to do this faster and more efficiently, one of my other friends suggested hashes, but again you are dealing with an outside object... So i went to work on this little script here. What the script does is read off the directory and automagically generate a script that will change the background, the cool thing about this script is that it doesnt read off the directory, this script has a list (or an array for non Python programmers) of files within the specified directory, so all the script does is generate the random number and execute the bg-switching command. rin times on my system are about .3 seconds, .4 for xrand setroot, but i dont have the C file my friend uses to test, so i've been trying to get him to try it out, but its catchup time in college, so no time to waste...

 

Firstly, this script is only for box window managers (i.e. blackbox, flixbox, openbox...) and it does run only on Unix based systems, that was the design...

 

to install the script, you need to run it, there is help there, then if you used the default method of bg switching you edit your crontab to add "0,5,10,15,20,25,30,35,40,45,50,55 * * * * python 'path to the python script generated (default lib.1.2.py)'" and enjoy (unless there are errors which, chances are, i can correct)

if you use feh method, you just need to run the script, it has a sleep and an infinite loop, so no problems there (but there are memory tradeoffs: it will have that array loaded all the time, but nothing compared to what windows does...)

 

oh, i should probably mention this before yo see the code, it's being designed so eventually there will be two files for it, a lib and an the main, so dont mind the function declarations there...

 

It's always better to have a few pairs of eyes look through the code than just one, i've been optimizing it a bit here and there for speed, but cant promice anything. remeber, this is still a beta, this is the first place outside my close circle of friends that i released it, so bear with me... oh and spread the word to flux/black/open box users!

 

and yes niksoft is me

 

#!/usr/bin/python -O
#Xrand Reloaded 1.2.0
#python script that creates a file to execute in order to change the
#background image in boxes so far
#by niksoft

##imports
import sys, sre
import re
import os
import commands, string

## functions
arg=sys.argv

#fc_file is a function that will create a file to be output to
#if the file is there, it will delete it and create a new one

def help_me():
   print "xrand_pyth.py -[options] [source] [path] n"
   print "[options] n"
   print "t a - ask before doing something n"
   print "t d - use default settings (instalation path is current directory, image folder path is /usr/share/pixmaps/gentoo/1024x768/) n"
   print "t h - help n"
   print "t m - changes  the way to change backgounds from esetroot to fehn"
   print "t v - verbose n"
   print "t s - set paths [location of image folder] [path to install to] nn"
   print "[use example]n"
   print "xrand_pyth.py -vas /usr/share/pixmaps/gentoo/2048x1024/ /home/user2/xrand/"
   sys.exit()


def fc_file(src):

# this will delete a file if it exists in order to completely and surely
# overwrite it

#    if os.path.exists(src):
#        try:
#            os.unlink(src)
#        except os.error, (errno, errstr):
#            raise DistutilsFileError, 
#                "could not delete '%s': %s" % (src, errstr)

   try:
       file_dat = open(src, 'w+', 10);
   except os.error, (errno, errstr):
       raise DistutilsFileError, 
           "could not create '%s': %s" % (src, errstr)
   return file_dat

#get_dir_listing is a function that returns a list of files in a
#directory

def get_dir_listing(dir):
   if os.path.exists(dir):
       dir_list = commands.getoutput("ls " + dir)
       return dir_list

def ask_me(msg):
   yn = string.lower(raw_input(msg + "nWould you like to continue?"))
   if yn == "n" or yn == "no":
       print "nExiting..."
       sys.exit()
   else:
       return

## main
#experimental
ask="false"
verbose="false"
path = "./"
method = "esetroot"
src = '/usr/share/pixmaps/gentoo/1024x768'

if len(arg)>1:
   if arg[1][:1] == "-":
       for letter in arg[1]:
           if letter == "-":
               continue
           elif letter == "a":
               ask = "true"
               continue
           elif letter == "m":
               method = "feh"
               continue
           elif letter == "v":
               verbose = "true"
               continue
           elif letter == "h":
               help_me()
               continue
           elif letter == "d":
               path = "./"
               method = "esetroot"
               src = '/usr/share/pixmaps/gentoo/1024x768/'
               break
           elif letter == "s":
               if not arg[3]:
                   help_me()
               path = arg[3]
               if not arg[2]:
                   help_me()
               src = arg[2]
               continue
           else:
               help_me()
               sys.exit()
               break
   else:
       help_me()
else:
   help_me()


if verbose=="true":
   print "/nGetting directory listing.../n"

#getting directory listing
dirlist = get_dir_listing(src)

#parse dirlist
dirlist = dirlist.split("n")

if verbose=="true":
   print dirlist

#create data to be put in file

if verbose=="true":
   print "/nGenerating file.../n"

data = "dir_list = ( '" + sre.escape(dirlist[0]) + "'"

for counter in range(1, len(dirlist), 1):   
#     data = data + ", '" + src + dirlist[counter] + "'"
    data = data + ", '" + sre.escape(dirlist[counter]) + "'"

data = data + ')'

if method == "esetroot":
   data = [data + "n", "src = '" + src + "'n", ["#import statementsn"], ["import random, commandsn"], ["#get a random integern"], ["rand_int = random.randrange(1, len(dir_list))n"], ["#execute Esetrootn"], ["error = commands.getoutput("/usr/bin/Esetroot -cf " +src + dir_list[rand_int])n"], ["#print errorn"]]
elif method == "feh":
   data = [data + "n", "src = '" + src + "'n", ["#import statementsn"], ["import random, commands, timen"], ["#loopn"], ["while 0=0:nt"], ["#get a random integern"], ["trand_int = random.randrange(1, len(dir_list))n"],["t#feh methodn"], ["terror = commands.getoutput("feh --bg-scale" + src + dir_list[rand_int])n"], ["t#sleepn"], ["ttime.sleep(300)n"]]
if verbose=="true":
   print data

#switch this to your home directory

if ask == "true":
   askq = "The program is about to overwrite " + src
   ask_me(askq)
data_file = fc_file(path+"lib1.2.py")

#writing data to file
for counter in range(0, len(data), 1):
   data_file.writelines(data[counter])

#close file
data_file.close() 

 

hey, these code tags format the code funny, but correctly...

Link to comment
Share on other sites

Well, i had a little time during the weekend to test my program here, and i found an error here:

data = [data + "n", "src = '" + src + "'n", ["#import statementsn"], ["import random, commands, timen"], ["#loopn"], ["while 0=0:nt"], ["#get a random integern"], ["trand_int = random.randrange(1, len(dir_list))n"],["t#feh methodn"], ["terror = commands.getoutput("feh --bg-scale" + src + dir_list[rand_int])n"], ["t#sleepn"], ["ttime.sleep(300)n"]]

this should be while 0 == 0: ...

Link to comment
Share on other sites

there is a description, but let me redescribe it...

This scritp is designed to create a script that will switch your background choosing randomly from a directory. The script generated only works on a box GUI (blackbox, fluxbox, openbox...) on a Unix-Based system, the installation instructions are in my post above.

 

What do i use it for? i run this script every time i have a new image/images in my gentoo artwork folder. After runnung startx command after, the background changes every 5 minutes (randomly and automagically) ...all the things i do to impress my windows-using friends... but its quiet nice to have a different bg every so often.

Link to comment
Share on other sites

  • 3 weeks later...

here's a new version of the script:

#!/usr/bin/python -O
#Xrand Reloaded 1.2.0
#python script that creates a file to execute in order to change the 
#background image in
#blackbox (fast but needs testing)
#by niksoft

##imports
import sys, sre, os, commands, string

## functions
arg=sys.argv

#fc_file is a function that will create a file to be output to
#if the file is there, it will delete it and create a new one

def help_me(err):
   if err <> "":
       print "n" + err + "nn"
   
   print "xrand_pyth.py -[options] [source] [path] n"
   print "[options] n"
   print "t a - ask before doing something n"
   print "t d - use default settings (instalation path is current directory, nttimage folder path is /usr/share/pixmaps/gentoo/1024x768/) n"
   print "t h - help n"
   print "t m - changes  the way to change backgounds from esetroot to fehn"
   print "tt r [num] - can be used with m only, this option will randomlyntttexecute "--bg-seamless" every one out or [num] nttttimes (randomly) (i don't know what it does,ntttbut it makes some background look nice)n"

   
   print "t s [path 1] [path 2] - set locations of the foldes:n"
   print "tt all paths must end with a "/"n"
   print "tt [path 1] - source folder where the images residen"
   print "tt [path 2] - path to where to put the result filen"
   print "tt n [name] - specify new script namenttt(default its lib[version].py)n"
   print "t v - verbose n"
   print "[use example]n"
   print "setuplib.py -vasnmr /usr/share/pixmaps/gentoo/2048x1024/ /home/user2/xrand/ bgswitch.py 10"
   sys.exit()


def fc_file(src):

## this will delete a file if it exists in order to completely and surely 
# overwrite it

#    if os.path.exists(src):
#        try:
#            os.unlink(src)
#        except os.error, (errno, errstr):
#            raise DistutilsFileError, 
#                "could not delete '%s': %s" % (src, errstr)
## end
   try:
       file_dat = open(src, 'w+', 10);
   except os.error, (errno, errstr):
       raise DistutilsFileError, 
           "could not create '%s': %s" % (src, errstr)
   return file_dat

#get_dir_listing is a function that returns a list of files in a 
#directory

def get_dir_listing(dir):
   if os.path.exists(dir):
       dir_list = commands.getoutput("ls " + dir)
       return dir_list

def ask_me(msg):
   yn = string.lower(raw_input(msg + "nWould you like to continue?"))
   if yn == "n" or yn == "no":
       print "nExiting..."
       sys.exit()
   else:
       return

## main
name="lib1.3.py" # name of the new file
rnd="" #random time
n=0 # used in sre.search
ask="false" # ask before writing
verbose="false" # verbose mode
path = "./" # default path
method = "esetroot" # method to use
src = '/usr/share/pixmaps/gentoo/1024x768/' # source

if len(arg) > 1:
   if arg[1][:1] == "-":
       for letter in arg[1]:
           if letter == "-":
               continue
           elif letter == "a":
               ask = "true"
               continue
           elif letter == "m":
               method = "feh"
               if string.find(arg[1], "r") <> 1:
                   for i in range(1, len(arg),1):
                       ## for testing only 
                       # answer = sre.search("[A-Za-z.>,</?;:'"{[]}()-_+=!@#$%^&*`~]", arg[i], flags=0)
                       # print "/nanswer: " + str(answer)
                       ## end
                       if not sre.search("[A-Za-z.>,</?;:'"{[]}()-_+=!@#$%^&*`~]", arg[i], flags=0):
                           n = 1
                           break
                   if n <> 1:
                       help_me("Missing [num] argument for the "r" tag")
                   rnd = arg[i]
               continue
           elif letter == "v":
               verbose = "true"
               continue
           elif letter == "h":
               help_me("Help")
               continue
           elif letter == "d":
               path = "./"
               method = "esetroot"
               src = '/usr/share/pixmaps/gentoo/1024x768/'
               break
           elif letter == "s":
               if not arg[3]:
                   help_me("You need to specify path for the "s" flag")
               path = arg[3]
               if not arg[2]:
                   help_me("You need to specify source for the "s" flag")
               src = arg[2]
               continue
           elif letter == "r":
               continue
           elif letter == "n":
              if string.find(arg[1], "s") != 1:
                  if not arg[4]:
                      help_me("You need to have a filename for the "n" flag")
                  name = arg[4]
                  continue
              else:
                  help_me("The "n" flag can only be used with the "n" tag")
           else:
               help_me("Error: wrong arguments")
               break
   else:
       help_me("Error: you must have a - before arguments")
else:
   help_me("Error no arguments")

## testing
#print  "ask: " + ask + "nverbose: " + verbose + "nmethod: " + method + "nsrc: "+ src +"nn: " + str(n) + "narg[i]: " + str(arg[i]) + "nname: " + name
#sys.exit()
##end

if src[len(src)-1] != "/":
   help_me("Error: the source path needs to end with a slash")

if verbose=="true":
   print "/nThe path checked out OK/n"
   print "Getting directory listing.../n"

#getting directory listing
dirlist = get_dir_listing(src)

#parse dirlist
dirlist = dirlist.split("n")

if verbose=="true":
   print dirlist

#create data to be put in file

if verbose=="true":
   print "/nGenerating file.../n"

data = "dir_list = ( '" + sre.escape(dirlist[0]) + "'"

for counter in range(1, len(dirlist), 1):    
#     data = data + ", '" + src + dirlist[counter] + "'"
    data = data + ", '" + sre.escape(dirlist[counter]) + "'"

data = data + ')'

#if method is esetroot, file will contain this data
if method == "esetroot":
   data = ["#!/usr/bin/python -On", data + "n", "src = '" + src + "'n", ["#import statementsn"], ["import random, commandsn"], ["#get a random integern"], ["rand_int = random.randrange(1, len(dir_list))n"], ["#execute Esetrootn"], ["error = commands.getoutput("/usr/bin/Esetroot -cf " +src + dir_list[rand_int])n"], ["#print errorn"]]

#else fist start with the basic beginning
else:
   data = ["#!/usr/bin/python -On", data + "n", "src = '" + src + "'n", ["#import statementsn"], ["import random, commands, timen"], ["#loopn"], ["while 0 == 0:nt"], ["#get a random integern"], ["trand_int = random.randrange(1, len(dir_list))n"], ["tcmd="feh --bg-scale "n"]]

#check if users wanted to use seamless filter randomly
   if rnd != "":
       data = data + [["trand=random.randrange(1, " + rnd + ")n"], ["tif rand==1:n"],["ttcmd="feh --bg-seamless " n"]]

#finish the file
   data = data + [["t#feh methodn"], ["terror = commands.getoutput(cmd + src + dir_list[rand_int])n"], ["t#sleepn"], ["ttime.sleep(300)n"]]
if verbose=="true":
   print data

#ask before writing

if ask == "true":
   askq = "The program is about to write to " + path + name
   ask_me(askq)
data_file = fc_file(path+name)

#writing data to file
for counter in range(0, len(data), 1):
   data_file.writelines(data[counter])

#close file
data_file.close() 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...