Geek Tools

20 Sep 2012

I use a lot of tools in my everyday computer live. Most of them runs in terminal (vim, mutt, zsh), but today's post is about a couple of useful GUI tools: GeekTool and Alfred.

Alfred

Alfred is a small program basically intended to run other apps. AFAIK its closest analog in Linux world is Krunner from KDE which I used a lot in old days. Alfred has more features than Krunner and it will become even more powerful when you buy Powerpack for £15. By the way, you need it anyway if you're going to use the tip below.

As for the tip, it's about iTunes integration: it's OK in most cases, but I was disappointed when I've known that Alfred's playlist is played only once without repetition. And there's no option that enables it.

But real hackers don't lay their heads down! To enable repeating the playlist you have to edit itunes.applescript.src file in Resources folder inside Alfred's package contents. As you may already guessed this is Applescript source file that's being compiled when Alfred starts. If you don't know Applescript and don't want to learn it here is my patch for v1.3.1(261):

126c126
< 		make new user playlist with properties {name:playlistname, song repeat: all}
---
> 		make new user playlist with properties {name:playlistname}

GeekTool

GeekTool, on the other hand, is used to display some useful information on your desktop. It's like good old widgets but without Dashboard needed to be active to see them. Conky does the same thing in Linux.

GeekTool has 3 types of widgets: file, image, shell script. File shows contents of some file on your HDD. Maybe it's useful for viewing logs or something like this, but I found this quite pointless. Image does the same, only shows it as image. It gets file or URL as argument. The most interesting part is Shell Script which shows output of some terminal tool on your desktop. This is really powerful. Besides, GeekTool can refresh this output automatically.

GeekTool

Here is a screenshot from my current desktop. Date and time were quite simple to get, currently playing track was not so simple, but still simpler than artwork from Last.fm. I'm going to tell about this last one.

The main idea is to download album cover, say, into /tmp/artwork.png and then show it with Image from GeekTool. I wrote simple daemon using Python and PyObjC which spies on iTunes and when it changes currently playing track detect artist and album and get cover from Last.fm if any exists. Here is daemon's code:

import requests
import json
import Foundation
from AppKit import *
from PyObjCTools import AppHelper

class SongInfo(NSObject):
    last_album = ""
    last_artist = ""

    def getSongInfo_(self, song):
        ui = song.userInfo()
        artist = ui.objectForKey_('Artist')
        album = ui.objectForKey_('Album')
        if self.last_artist != artist and self.last_album != album:
            params = {
                "method" : "album.getinfo",
                "api_key": "PUT_HERE_YOUR_API_KEY",
                "artist" : artist,
                "album"  : album,
                "format" : "json"
            }
            r = requests.get("http://ws.audioscrobbler.com/2.0/",params=params)
            album_info = json.loads(r.text)
            if album_info.get("album") and album_info["album"].get("image"):
                img_url = [x["#text"]
                            for x in album_info["album"]["image"]
                            if x["size"] == "large"]
                if img_url:
                    f = open("/tmp/artwork.png", "w")
                    f.write(requests.get(img_url[0]).content)
                    f.close()
                    self.last_artist = artist
                    self.last_album = album

nc = Foundation.NSDistributedNotificationCenter.defaultCenter()
song_info = SongInfo.new()
nc.addObserver_selector_name_object_(song_info, 'getSongInfo:', 'com.apple.iTunes.playerInfo',None)

AppHelper.runConsoleEventLoop()

Now lets put this daemon to autostart. I did it with launchd. First, create file com.dancingrobot84.lastfm-artwork.plist in ~/Library/LaunchAgents with this content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
    <key>Label</key>
    <string>com.dancingrobot84.lastfm-artwork</string>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>UserName</key>
    <string>YOUR_USERNAME</string>
    <key>ProgramArguments</key>
    <array>
        <string>python</string>
        <string>FULL_PATH_TO_DAEMON</string>
    </array>
    <key>WorkingDirectory</key>
    <string>YOUR_HOME_DIR</string>
    </dict>
</plist>

Second, load daemon with this command

launchctl load -w ~/Library/LaunchAgents/com.dancingrobot84.lastfm-artwork.plist

Now you're going to have a cover of your currently playing track in /tmp/artwork.png.