Showing posts with label pygtk. Show all posts
Showing posts with label pygtk. Show all posts

Thursday, November 8, 2007

Episode selector dialog for gPodder

Today after University, I decided to hack a feature into gPodder that I have thought about for a while - the episode selector dialog. It should be used in several user interaction situations where a simple binary question is not specific enough ("delete old episodes?" vs "which of these old episodes do you really want to remove?"). So I set out implementing this neat little feature and when I looked at the watch and decided that I had to leave for math classes, most of the episodes selector has been implemented, with quite some fancy features and options. I used the last two hours to look through the my working copy diff to fix some obvious omissions, but as of now, the code of the new episode selector is already in SVN. I've attached some screenshots so you can see how it looks.

Thanks to lambda expressions, PyGTK coolness and getattr, i.e. accessing attributes by name, this dialog is now quite customizable and the code is still readable and (compared to what other languages would have yielded), small. If you are using gPodder, be sure to check out the current SVN trunk head.

One feature I used several times was enumerate() - you give an iterable as parameter, and get a generator that yields tuples with two elements - a zero-based index and the values you would normally get from the iterables directly. So, instead of writing code like this:
index = 0
for item in items:
print 'item %d is %s' % ( index, item )
index += 1
you can simply write
for index, item in enumerate( items):
print 'item %d is %s' % ( index, item )
which isn't only nicer, but you save two lines and the code is IMHO more readable (you instantly recognize "index" as being related to the for loop in the second code snippet).

Wednesday, September 26, 2007

PyGTK applications on Windows

One advantage that you automatically gain when writing Python programs is that they are portable to several other mainstream operating systems (although there are some problems with specific extensions, etc..).

So, after releasing gPodder 0.10.0, which has now only one strict dependency on a pure Python module (feedparser), I wanted to try out if I could get gPodder running on Windows (I have tried it once before, but back then I was spawning a wget process to do the actual downloading, which was kind of awkward on the Windows platform).

What you need to get this working is Alberto Ruiz' All-in-one PyGTK Win32 installer and a check-out of the current SVN trunk head of gPodder. To check out a working copy from a Subversion repository on Win32, you can use TortoiseSVN.


I've found some divide-by-zero errors that I didn't see happening on Linux, so I could quickly fix them in our Subversion repository. I also got rid of some old symlinking code that I didn't use anymore, because symlinks on Windows isn't really possible (except for Vista maybe). Other than that, there were just some minor problems with my code being Unix/X11-specific, for example I'm checking for the $DISPLAY variable in the main script, which isn't needed on Win32.

There were other minor annoyances which I haven't dealt with yet, but which don't interfere with the basic functionality of gPodder:
  • Running .mp3 or .avi files with the preferred media player (how do I do that on Win32?)
  • Getting a GTK Icon Theme into my GTK installation, so all icons in gPodder display properly
  • Removing the GUI for iPod synchronization (or get libgpod + Python bindings working on Win32)
  • Testing, testing testing :)
I wonder if it's possible to use Py2exe to create a nice, self-contained Win32 package of gPodder that has Python2.5, the GTK runtime, PyGTK and python-feedparser integrated and works without installing anything.

Thursday, September 13, 2007

X11 idle time and focused window in Python

For my Evolution New Mail Notification script, I wanted to make the notification popups not enabled when I'm already working within evolution (e.g. the Evolution window is focused) and I also didn't want to play sounds when I'm working on the computer, because I will see the visual notification, anyway (e.g. the X11 idle time is less than some specified timeout).

To accomplish that, I had to write a bit of Python code for two simple tasks:
  • Get the window name and/or class of the currently focused window
  • Get the idle time of the X11 session, e.g. the time since the last input event
The window name/class getting can be done with the help of the Python X Library and the idle time can be done using some obscure ctypes loading of libXss.so and doing a bit of C-bindings stuff, which I found by searching the web. Here, I want to share the code with you in case you need it for some project of yours:

Window Name and Class for the focused window
import Xlib.display
display = Xlib.display.Display()
focus = display.get_input_focus()
print "WM Class: %s" % ( focus.focus.get_wm_class(), )
print "WM Name: %s" % ( focus.focus.get_wm_name(), )
X11 Idle Time using the XScreenSaver extension
import ctypes
import os

class XScreenSaverInfo( ctypes.Structure):
""" typedef struct { ... } XScreenSaverInfo; """
_fields_ = [('window', ctypes.c_ulong), # screen saver window
('state', ctypes.c_int), # off,on,disabled
('kind', ctypes.c_int), # blanked,internal,external
('since', ctypes.c_ulong), # milliseconds
('idle', ctypes.c_ulong), # milliseconds
('event_mask', ctypes.c_ulong)] # events

xlib = ctypes.cdll.LoadLibrary( 'libX11.so')
dpy = xlib.XOpenDisplay( os.environ['DISPLAY'])
root = xlib.XDefaultRootWindow( dpy)
xss = ctypes.cdll.LoadLibrary( 'libXss.so')
xss.XScreenSaverAllocInfo.restype = ctypes.POINTER(XScreenSaverInfo)
xss_info = xss.XScreenSaverAllocInfo()
xss.XScreenSaverQueryInfo( dpy, root, xss_info)
print "Idle time in milliseconds: %d" % ( xss_info.contents.idle, )
If you're interested in a real-world example usage of this code, feel free to check out my evolution-newmail.py new mail notification script that works with Evolution over D-BUS.

Sunday, July 15, 2007

Exaile: Python-based GTK media player

I don't know on which planet I got linked to Exaile, a GTK audio player written in Python. Anyway, I installed it some days ago and downloaded some plug-ins (IM status, which works great with Pidgin; and Mini Mode, which makes Exaile about as high as the Gnome panel and only about one third of my screen wide).

Exaile is great, it has a slick, but simple interface, nice features (the music library is created by adding paths to my music collections, which is a no-nonsense way of managing the library ;). Bulk downloading album art and album cover search are great features. Last.fm integration is built-in, and DAAP support can be enabled by installing a plug-in.

There are still some annoyances: For example, tracks with no album set are displayed as "Trackname from by Artist", i.e. the album title is simply missing. But thanks to the great build/run architecture of Exaile that makes it possible to patch and test/debug directly in the SVN working directory, I was quickly able to come up with a patch, which will hopefully be included in Exaile soon.

Other than that, I can only recommend Exaile. It is in active development, and the problems and bugs that are currently present will hopefully be patched out in future versions :)