Installing Qtile on Ubuntu 11.10 (Oneric Ocelot)

Recently, there has been some discussion on qtile-dev about installing the latest and greatest version of qtile. Unfortunately, the install process has historically been a journey into dependency hell, since distributions didn't have the latest versions of some libraries required by qtile. The good news is that this has mostly been fixed (although very few documents anywhere state this), so it's hard to know what to install by hand and what you can use packages for.

To complicate matters more, there are several versions of xpyb floating around, none of which have working build systems! If you knew enough about pkg-config and weren't afraid of manually installing files, you could get everything to work, but it did bar the "normal user" from installing qtile. Hopefully this blog post will clarify a few things.

First, what dependencies do you need to install? Contrary to what the docs say, in 11.10 (and presumably later versions of Ubuntu), you don't need to build your own cairo or xcb. You can simply:

sudo apt-get install xcb-proto libxcb1-dev python-xcbgen
libcairo2-dev

You will have to build three things by hand: xpyb, py2cairo, and qtile itself. The other day I sat down and fixed the build system for xpyb, so you should be able to just:

git clone git://github.com/tych0/xpyb-ng.git
cd xpyb-ng
sudo python setup.py install

After that, you'll need to install py2cairo. The waf based build doesn't appear to detect xpyb correctly, so you'll need to go the autoconf route. Even with autoconf, the build system is slightly broken, so you'll need to be explicit about what directories to look in for xpyb.h. If you used the above build of xpyb, you can:

git clone git://git.cairographics.org/git/py2cairo
cd py2cairo
CFLAGS=-I/usr/local/lib/python2.7/xpyb ./configure
sudo make install

Then, you can clone your favorite qtile repo and everything should Just Work! If you want to clone my copy of qtile (which includes several bug fixes and enhancements):

git clone https://github.com/tych0/qtile
cd qtile
sudo python setup.py install

If you have any questions or problems, feel free to mail qtile-dev or me directly. I am going to try and package qtile and put it in a PPA, but I doubt I will get to that for another few weeks. This should help anyone who is interested enough to build it in the meantime, though!

Viridian/Ampache local control

Recently at work I've been using Viridan to listen to music at work. It has its warts, but generally works pretty well. There's even an XMLRPC server built in, so you can control it remotely. However, there's not a huge number of clients out there, so I wrote my own little script so that I could start and stop it from a Qtile keybinding, and I thought I'd put it up here for anyone else who is interested. Here's an example session:

smitten:~$ ./vif.py 
./vif.py [rpc_call(s)]
   availible methods are:
     get_current_song
     get_state
     get_volume
     next
     play_pause
     prev
     set_volume
     volume_down
     volume_up
smitten:~$ ./vif.py get_current_song
{'artist_name': 'Meshuggah','song_title': 'Stengah', ...}
smitten:~$ ./vif.py next
True

Hopefully someone else finds it useful :-)

Photos from my Colorado adventure

Hello! I just completed another successful two and a half weeks touring the Colorado mountains. Although the snow was not great (Winter Park only has around a 15 inch base, and over half the mountain was closed), I still had a good time! Rather than do a lot of aggressive skiing (the conditions would have made aggressive skiing fairly dangerous), I tried a bunch of new things instead! The most interesting new thing was probably the ski bike, and I am now a licensed snow cyclist! My dad and I both took lots of pictures, and he's posted both the ones from his camera and my camera on his web page.

I did three summits during the trip, two of Mt. Charles which is roughly 12,050 feet, and one of Mt. Prospect which is roughly 11,700 feet. I took a panorama (which I've yet to stitch together) of the view on Mt. Prospect, and my dad took one of Mt. Charles, so eventually when we get those stitched together, I'll post them as well. Anyway, if you're heading out west, here's to hoping you have more snow than we did! Even though the backcountry was bare in spots, we still had a lot of fun goofing around (you might notice some defilement of a USGS marker in the photos ;-).

Python "binding" for Ampache

Ahoy!

Just writing a quick post to pimp my new Ampache "bindings", which are called ampyche, naturally ;-). I slapped them together one afternoon mostly to get an understanding of the Ampache API, so that's why I used my native language. I have no specific plans for any python applications using them, but I'm interested in improving the stability of Android-based Ampache clients, as well as adding support for Ampache to Clementine, so I thought this would be a good place to start.

In any case, I hope someone finds them useful! Happy hacking!

Unifying Logitech Devices on Linux

I was recently given a Logitech K800 keyboard and a Logitech Performance Mouse MX, both of which are great devices. I picked them because wireless-ness is useful for ergonomic reasons, and they have rechargeable batteries, and you can attach them both to the same USB input, so you have fewer cables lying around.

Naturally, though, when I unboxed them I found out that you can only unify them to the same receiver with Windows-only software. There are a number of other features that are only usable with the Windows-only software, but I figured there would be a hardware sync process. Unfortunately, there's not a Logitech supported one.

There is, however, a community developed one! There's a short C program with a bunch of magic numbers which send commands to the device and cause it to unify with a new device. Unfortunately, the program comes with no directions, so I thought I'd post about how to do it. First, put the program in pairing_tool.c, as suggested in the post. Then, compile it with:

gcc -o pairing_tool pairing_tool.c

To run it, we need to figure out where the Logitech unifying receiver is. The program wants the hidraw device corresponding to the unifying receiver. To find this out, you can look in /sys/class/hidraw/hidraw*/device/uevent. In my case, the device is hidraw2, and the output looks like this:

smitten:~$ cat /sys/class/hidraw/hidraw2/device/uevent 
DRIVER=generic-usb
HID_ID=0003:0000046D:0000C52B
HID_NAME=Logitech USB Receiver
HID_PHYS=usb-0000:00:1a.0-1.4/input2
HID_UNIQ=
MODALIAS=hid:b0003v0000046Dp0000C52B

So, we can now unify the devices with the following command:

sudo ./pairing_tool /dev/hidraw2

And then power on your device as the tool tells you to. I think there's some timeout on this, because the first time I did it I waited a few minutes and then powered on the device, and it didn't work. So, have your device ready and do it seconds after you run the pairing tool, and it should all work fine. HTH!

Mutt Sidebar Configuration

I am a mutt user (in fact, I'm a mutt-sidebar user). That means several things, one of which is that I spend a nonzero amount of time configuring my e-mail client to behave as I want it to. I am also a vim user, and in the spirit of loving vim, I set out on an adventure to make everything look and feel like vim. A natural thing to want to do is be able to navigate the sidebar (i.e. the folder list) with j and k keys as one does in vim. Reasonable attempts at this fail for various reasons, and I hope this post will explain why and also how to do what you want.

First, a natural thing to want to do is to bind sidebar navigation to <ctrl>+j and <ctrl>+k, since the <ctrl> binding indicates somehow that the navigation is "slightly different", and therefore is a good mnemonic for a "slightly different" kind of up and down movement. To do this, you could put something like:

bind index,pager \ck sidebar-prev
bind index,pager \cj sidebar-next

at the end of your ~/.muttrc. However, this has an unexpected result: moving up and down in the menu works just fine, but now pressing <return> also moves you down in the sidebar, instead of opening the highlighted message (its default) or whatever else you had it set to.

The problem is that <ctrl>+j and <return> are actually the same character. That is, when you press <ctrl>+j the terminal interprets it and sends an ASCII 10 (the LF character), which is the same thing that <return> sends. In fact <ctrl>+* (where * is any character a-z) is bound to some control code (it's just that most of them are unused in modern applications, e.g. <ctrl>+i is an alias for tab). Unfortunately that means we can't bind <ctrl>+j and <return> to different things in mutt, since they're actually the same character.

So what's the workaround? Well, I decided that <alt> is just as reasonable as <ctrl>. Running :exec what-key told me that \252 (i.e. octal 252) is <alt>+j, so I can add the following lines to ~/.muttrc:

bind index,pager \253 sidebar-prev
bind index,pager \252 sidebar-next

but it didn't work! Mutt Well, it might work for some people, depending on their terminal configurations. According to the Rute User's tutorial and Exposition:

The alt modifier (i.e. Alt-?) is in fact a short way of pressing and releasing Esc before entering the key combination; hence Esc then f is the same as Alt-f--UNIX is different from other operating systems in this use of Esc.

So what's the issue? Well, some terminals do this by default, and some don't. In xterm, the default is not to convert <alt> characters into the escape sequences mutt expects. However, by putting

xterm*metaSendsEscape: true

in your ~/.Xresources and running xrdb ~/.Xresources and restarting xterm, it /will/ interpret <alt> keypresses correctly, and your <alt>+j keybindings will work.

Google Voice ncurses interface

For a while I have been using a Google Voice number as my primary texting number since it doesn't cost any money and has the additional benefit that when I'm at a computer, I can type text messages on a regular keyboard instead of on my tiny phone keyboard. This is all well and good, except I don't particularly care for the web interface; not because it's bad, but simply because it requires you to have a web browser open.

To solve this, I wrote an ncurses based "chat" client, gvchat. It provides and instant messaging interface for the most recent text message your GV account has received. When someone new texts you, it seamlessly switches to that new thread. At this point there is no way to initiate new texts, but I plan on growing the feature set in the coming months. However, for now it fits my needs so I thought I'd put it up for other people in the same boat.

Additionally, the client has a class 'Chat', which implements a crude ncurses based chat interface. As this improves, my hope is to add an XMPP backend for it as well. Any ncurses tips and tricks (or pointers to libraries which already have this functionality and are built on top of ncurses) are much appreciated!!

A Tiling Window Manger

Ahoy! At the recommendation of one of my friends, I've recently begun using a tiling window manger. Although he recommended xmonad, I decided to instead to go with a different project, qtile. I got myself a github account, since that is the primary avenue for qtile development. This means you can run the same WM code as I do :-). (I also posted the code for the framework that powers this blog, something I've been meaning to do for a while but have not gotten around to.)

I wrote a widget for displaying the currently playing track from your favorite player which implements MPRIS, and I would be interested in any feedback other qtile users have, so feel free to send me or qtile-dev e-mail if you play with it! The widget can be found in both my fork of qtile and in the main fork. It depends on python-dbus, things like Ubuntu's update-manager do too, so it's probably installed for most users. To use it, you can simply put

widget.Mpris(objname='org.mpris.awesome_mpris_player')

in your qtile config.py. objname should be whatever the name of your MPRIS player is. You can figure out what this is by running dbus-notify and starting your player, and see what name it requests when it issues RequestName. For example, Clementine's is org.mpris.clementine (and is also the default).

Happy hacking!

Rendering your current Clementine track in Conky

I've been using Clementine as a replacement for Amarok for the last few months (it's fairly feature complete, and you don't have to have all of KDE loaded into memory, so it is actually fast). As I also use Conky, it's only natural to want the currently playing track to be rendered in Conky. This isn't too hard, since Clementine exposes this information via dbus. You can see code to do this below:

#!/bin/bash
TRACK=`qdbus org.mpris.clementine /TrackList \
org.freedesktop.MediaPlayer.GetCurrentTrack`
qdbus org.mpris.clementine /TrackList \
org.freedesktop.MediaPlayer.GetMetadata $TRACK \
| sort -r | egrep "^(title:|artist:)" | sed -e "s/^.*: //g" \
| sed -e ':a;N;$!ba;s/\n/ - /g' | head -c 36

I put this in a script called nowplaying, and when run, it gives me output in Track name - Artist format. I cut off the output after 36 characters because that's about the size of my Conky window, and songs with longer names will cause Conky to automatically resize its window, which I think is distracting. You can chop the last bit off if you don't want this. Also, although I generally prefer Artist - Track Name notation, I can usually tell who the artist is, so I listed the track name first in case the combination was over my 36 character limit. You can switch it back to Artist - Track name by removing the -r flag from the sort command above.

Now, to get this information into Conky, add a line to your ~/.conkyrc that looks something like this:

Now playing: ${execi 10 ~/config/bin/nowplaying}

Every 10 seconds, this will ping Clementine and ask it what is playing. If nothing is playing (or clementine is not running), this will simply render the empty string.

Bug in GTFO

Uh oh! If you've been browsing this site for the last few days, you've probably noticed some strange behavior. For some reason I'm getting a lot more hits than I was when I originally designed the framework, and it revealed a bug (a race condition, if you're interested). Or at least, I think that was the bug. I'm not totally convinced that's what it was, but that's my educated guess.

Anyway, I believe I've fixed the bug, and all should be happy now. Life is busy, busy, busy now that classes have started. I'm planning to do a century ride at the end of September, though, so I need to find time to keep riding :-)