Display New Episodes of Your Favorite Shows on Your Desktop (It's a GeekTool Geeklet)

With the fall TV season about to start I wanted a better way to keep track of when new episodes of my favorite shows are airing. Using GeekTool, this little script displays the series and title of new episodes airing today on my desktop.

If you're new to GeekTool, I suggest reading this tutorial.  It will make everything here much clearer.

This script uses thetvdb.com's new shows rss feed and compares it to the api feed of shows you've selected as favorites on the site.  You can find your account id at the bottom of your account settings on thetvdb.com.  Of course you'll need to register if you don't already have an account, but it's a free site.

It uses the feedparser python lib to handle the rss. You can download that here. (very easy to install)

thetvdb.com new shows list is only updated once a day, so please make sure to set your refresh rate to once a day so it doesn't cause too much traffic for the site. They are an underfunded project so it's important to avoid unnecessary hits.


Once you have feedparser installed, just drag a shell module from GeekTool to the desktop and paste this script into the command field.

#!/usr/bin/env python
import feedparser, urllib2
from xml.etree import ElementTree as ET
# =========== CONFIG =============
# Insert your account id here. You can find it at 
# the bottom of your account settings page on thetvdb.com
ACCOUNTID = 'C2920FF6804FD948'
# ================================

new_shows = feedparser.parse('http://thetvdb.com/rss/newtoday.php')
favorites_feed = urllib2.urlopen('http://thetvdb.com/api/User_Favorites.php?accountid='+ACCOUNTID)
favorites = ET.XML(favorites_feed.read())
shows_list = []

for new_show in new_shows.entries:
 new_show_series = new_show.links[0].href
 new_show_series_id = new_show_series[new_show_series.find("seriesid=")+9:new_show_series.find("&seasonid")]
 for favorite in favorites:
  if(favorite.text == new_show_series_id):

print "New episodes of favorite shows airing today:"   
if (len(shows_list)>0):
 for shows in shows_list:
  print "* "+shows
 print "* No new shows today"

Leave a comment or post a screenshot of it on your desktop.


Pie Chart Clock Geeklet for Geektool

Here is another fun clock Geeklet for you to use with GeekTool on the Mac.  This one displays three pie chart layers that gives you sort of an abstract looking clock

Here's how it looks on my desktop:

The script creates the three layers separately so you can position them any way you like.  In my example I stacked the images on top of each other with decreasing levels of transparency.

This Geeklet uses ImageMagick so make sure you have that installed before trying to set this up.  If you're not sure how, just install MacPorts and then type this in terminal

sudo port install imagemagick

Once you have imagemagick ready to go, drag a shell module from the GeekTools preference pane to the desktop and past this script into the command field

#!/usr/bin/env python

# File pie_chart_clock.py
# Created 9/5/2011
# Scott McClung
# Generates pie chart images based on the current system time
# Pie chart calculations the build_slices function were taken from piechart.py 
# written by Gregory Pittman. He has a detailed explanation of drawing .svg pie
# charts at http://wiki.scribus.net/canvas/Making_a_Pie_Chart
from __future__ import division

import os,time,math

# ============= CONFIG ==============
# location of ImageMagick
# this is the filename/path that will be used for the resulting images
# you can change these values to determine the size of the hour
# and minute pie charts
# colors for the time slice of each chart
# color for the background
# enter "none" for a transparent background
# add shadow under the pie charts by entering a value for the shadow depth
# for no shadow set the depth value to 0
hours_shadow_depth = 10
minutes_shadow_depth = 4
seconds_shadow_depth = 4

# ===================================

# populate the current time values
# the two slices of each pie are the current time slice and the
# slice representing the time left to complete the circle
hrs_slices = [hrs,(12-hrs)]
mins_slices = [mins,(60-mins)]
secs_slices = [secs,(60-secs)]
# There are always two slices of the pies and we'll display one or the other based
# the time of day.  We'll put both of them in a list for now.
hrs_path = []
mins_path = []
secs_path = []

def build_slices(radius, slices, parity):
 path = []
 total = 0
 i = 0
 seg = 0
 startx = radius + 20  # The screen x-origin: center of pie chart (a little padding is added to radius)
 starty = radius + 20  # The screen y-origin: center of pie chart (a little padding is added to radius)
 lastx = radius    # Starting coordinates of 
 lasty = 0     # the first arc

 for n in slices:
  total = total + n  # we have to do this ahead, since we need the total for the next for loop

 for n in slices:
  arc = "0"                   # default is to draw short arc (< 180 degrees)
  seg = n/total * 360 + seg   # this angle will be current plus all previous
  if ((n/total * 360) > 180): # just in case this piece is > 180 degrees
   arc = "1"
  radseg = math.radians(seg)  # we need to convert to radians for cosine, sine functions
  nextx = math.cos(radseg) * radius
  nexty = (math.sin(radseg) * radius)
  if (n == 0 and not parity):
   arc = "1"
   nexty -= 1
  # The weirdly placed minus signs [eg, (-(lasty))] are due to the fact that
  # our calculations are for a graph with positive Y values going up, but on the
  # screen positive Y values go down.
  path.append("path 'M "+str(startx)+","+str(starty) + " l "+str(lastx)+","+str(-(lasty))+" a" + str(radius) + "," + str(radius) + " 0 " + arc + ",0 "+str(nextx - lastx)+","+str(-(nexty - lasty))+ " z'")
  # We are writing the XML commands one segment at a time, so we abandon old points
  # we don't need anymore, and nextx becomes lastx for the next segment
  lastx = nextx
  lasty = nexty
  i += 1

 return path

def create_shadow(depth):
 if (depth>0):
  shadow = " \( +clone -background black -shadow 60x"+str(depth)+"+"+str(depth)+"+"+str(depth)+" \) +swap -background none -mosaic "
  shadow = ""
 return shadow

def select_path(parity,time,arr_path):
  return arr_path[0]
 elif(time == 0):
  return arr_path[0]
  return arr_path[1]

# build hours pie
parity = bool(time.strftime("%p")=="AM")
hrs_path = build_slices(hours_radius,hrs_slices,parity)
hrs_img_size = str((hours_radius + 20) * 2)
hrs_path_command = select_path(parity,hrs,hrs_path)

# build minutes pie
parity = not bool(hrs & 1)
mins_path = build_slices(minutes_radius,mins_slices, parity)
mins_img_size = str((minutes_radius + 20) * 2)
mins_path_command = select_path(parity,mins,mins_path)

#build seconds pie
parity = not bool(mins & 1)
secs_path = build_slices(seconds_radius,secs_slices, parity)
secs_img_size = str((seconds_radius + 20) * 2)
secs_path_command = select_path(parity,secs,secs_path)

# Draw the images using ImageMagick
# the nature of the pie chart math results in the path drawing the pie charts
# counter clockwise and starting from the 15 minute mark.  The simplest solution
# is to just have ImageMagik rotate and flop the image after it's drawn.
command_string = converter
command_string += " -size "+hrs_img_size+"x"+hrs_img_size+" xc:"+hours_background+" -fill "+hours_color+" -stroke none -draw \""+hrs_path_command+"\" -rotate \"-90\" -flop "+ create_shadow(hours_shadow_depth) + hours_img_file

command_string = converter
command_string += " -size "+mins_img_size+"x"+mins_img_size+" xc:"+minutes_background+" -fill "+minutes_color+" -stroke none -draw \""+mins_path_command+"\" -rotate \"-90\" -flop " + create_shadow(minutes_shadow_depth) + minutes_img_file

command_string = converter
command_string += " -size "+secs_img_size+"x"+secs_img_size+" xc:"+seconds_background+" -fill "+seconds_color+" -stroke none -draw \""+secs_path_command+"\" -rotate \"-90\" -flop " + create_shadow(seconds_shadow_depth) + seconds_img_file

Set it to update as frequently as you like.  I don't recommend setting to update too often if you're using a laptop as it will shorten your battery life a bit.  I find running it every 5 or 10 seconds still has the visual effect I want but doesn't chew up too many cycles.

Then drag 3 image modules to the desktop and point one to each of the three images created in your home directory.
  • pie_chart_clock_hrs.png
  • pie_chart_clock_mins.png
  • pie_chart_clock_secs.png

Set them to update on the same schedule as your shell module and then position and size to taste.

You can change the file names and location, pie radius, pie slice color, background color, and shadow depth by updating the values in the CONFIG section of the script if you'd like a different look and feel.

Thanks to Gregory Pittman and his demo on generating SVG pie charts with python.  You can see his work here: http://wiki.scribus.net/canvas/Making_a_Pie_Chart  Could not have figured this out without that tutorial.

If you installed ImageMagick using a different method than MacPorts, you will probably need to update the CONFIG section to point to the correct installation location for your system.

Feel free to leave some feedback or post a screenshot of your GeekTool setup!


Binary Clock Geeklet for GeekTool

I've always been fascinated by the binary clock so I made a desktop version that works with GeekTool.  If you haven't played with GeekTool for Mac yet, check it out here.

Edit: One of the downsides to GeekTool is the lack of documentation.  If you're just getting started with it, I just came across this great tutorial to help get you going.

Here is a screen shot of the final product

This geeklet requires ImageMagick so make sure you have that installed first.  If you're not sure how, start by installing MacPorts and then enter this command in terminal.

sudo port install imagemagick

Once you have ImageMagick installed, you need two image files to represent the on and off state of the lights.  These are the two images I'm using in the screen shot above:
Make sure that you save them as .png so the transparency is preserved.  By default the script will look for them in your home directory so just put them there for now.  It really doesn't matter what two images you use, just make sure that both files have the same outer dimensions so the columns line up correctly.  You can change the image location and the image filenames in the CONFIG section of the script.

Now drag a shell script module from GeekTool to the desktop and paste this script in to the command field.

# ======= CONFIG ============================================
# set this to the location of ImageMagick's convert command
# set this to the location where your Image geeklet will look
# set these to the image files you're using for on and off
# do not use '0' or '1' in your image filenames or it will cause confusion in the script below.
# set this to the binary reference you want to use for each number. (0-9)
# the image is designed to reflect time from the bottom up, but
# since the column stack is built from the top down, these numbers may
# appear to be backwards.
    BINARY=("0 0 0 0" "0 0 0 1" "0 0 1 0" "0 0 1 1" "0 1 0 0" "0 1 0 1" "0 1 1 0" "0 1 1 1" "1 0 0 0" "1 0 0 1")
# ===========================================================

hr=$(date '+%I')
min=$(date '+%M')
sec=$(date '+%S')

for index in 1 2 3 4 5 6

$CONVERTER     \( ${col[1]} -append \) \
            \( ${col[2]} -append \) \
            \( ${col[3]} -append \) \
            \( ${col[4]} -append \) \
            \( ${col[5]} -append \) \
            \( ${col[6]} -append \) \
            +append $OUTFILE

Set the shell Geeklet to refresh every 5 seconds or so.  You can have it update more frequently, just be aware of system resources.

Now drag an image module from GeekTool to the desktop and point the url field to the binary_clock_img.png file that should now appear in your home directory.  Set it to update at the same frequency as the shell Geeklet (5 seconds) and then size and position it to taste.

If you find that the binary_clock_img.png file is not being created, check that the CONVERTER file location in the script is set correctly for your ImageMagick installation.  By default, MacPorts will put it in /opt/local/bin/ but it may be in a different spot if you used some other method to install. (e.g. /usr/local/bin/)

Please leave constructive feedback below


Super Fuzzy Clock Geeklet

I recently discovered GeekTool for Mac and am an instant fan.  It allows you to layer scripts and images over your desktop to create a very custom view of basically anything you want.
Find out more about it here: http://projects.tynsoe.org/en/geektool/

Once you have it installed, head over to http://www.macosxtips.co.uk/geeklets/ to find some great little scripts to add.  Since there is very little documentation on the tool, studying these scripts is your best way to figure out how this thing works.
GeekTool isn't for the faint of heart so make sure your geek cred card hasn't expired before you start playing with it.

Here are a couple scripts that I put together this week that you might like.

Fuzzy Clock
There are a few fuzzy clocks in the geeklets list at macosxtips.com but I like my clocks to be super fuzzy and contain a bit more variety in the phrasing than what was already posted.  I also wanted the words to have some reflection on the desktop.

To make this script work you'll need to install imagemagick which is easily done through MacPorts (or Homebrew)
sudo port install imagemagick

Imagemagick isn't an easy beast either but with the help of Brett's post here, I was able to get the reflection to look like I wanted.

Once you have Imagemagick installed, drag a new shell module from the GeekTool app to the desktop and paste this script in the command field. Set it to refresh every 5 seconds or so.

# ======= CONFIG ============================================
# set this to the location of ImageMagick's convert command
# set this to the location where your Image geeklet will look
# set this to the font and font size you want to use for the text
# ===========================================================

# don't mess with these
NUM_WORDS=(one two three four five six seven eight nine ten eleven twelve)
FUZZY_WORDS=("just after" "just after" "a few minutes past" "a few minutes past" "five after" "five after" "five after" "almost ten after" "almost ten after" "ten after" "ten after" "ten after" "almost a quarter after" "almost a quarter after" "a quarter past" "a quarter past" "a quarter past" "almost twenty past" "almost twenty past" "twenty past" "twenty past" "twenty past" "almost twenty-five after" "almost twenty-five after" "twenty-five after" "twenty-five after" "twenty-five after" "almost half past" "almost half past" "half past" "half past" "half past" "almost twenty-five to" "almost twenty-five to" "twenty-five to" "twenty-five to" "twenty-five to" "almost twenty to" "almost twenty to" "twenty to" "twenty to" "twenty to" "almost a quarter to" "almost a quarter to" "a quarter to" "a quarter to" "a quarter to" "almost ten to" "almost ten to" "ten to" "ten to" "ten to" "almost five to" "almost five to" "five to" "a few minutes before" "a few minutes before" "just about" "just about")

# create the fuzzy clock phrase
hrs=$(date '+%-l')
mins=$(date '+%-M')
if [ "$mins" -eq "0" ] 
    phrase="${HEADER} ${hr} o'clock"
elif [ "$mins" -lt "31" ] 
    phrase="${HEADER} ${min} ${hr}"
    phrase="${HEADER} ${min} ${hr}"

# create the image of the time phrase
echo ${phrase}|$CONVERTER -background none -fill white -font ${FONT} -pointsize ${FONTSIZE} -trim label:@- $resultfile

# set the width and height variables
ww=`$CONVERTER $resultfile -format "%w" info:`
hh=`$CONVERTER $resultfile -format "%h" info:`
hhr=`$CONVERTER xc: -format "%[fx:$hh*40/50]" info:`

# clone the original image, flip it, composite a gradient and append it below the original
$CONVERTER $resultfile \
\( -size ${ww}x0 xc:none \) \
\( -clone 0 -flip +repage \) \
\( -clone 0 -alpha extract -flip +repage \
-size ${ww}x${hh} gradient: +level 0x50% \
-compose multiply -composite \) \
\( -clone 2 -clone 3 -alpha off -compose copy_opacity -composite \) \
-delete 2,3 -channel rgba -alpha on -background none -append $OUTFILE
exit 0
To change the font size or style just update the variables at the top of the script. You can also adjust the location where you want the resulting image to be saved. By default it saves it to your home directory.

Next drag an image module from GeekTool to the desktop and in the url field, select the 'reflected_time.png' file which should now be located in your home directory. Set the image to update every 5 seconds and you are good to go.
Position and resize the image to taste.

Feel free to leave constructive feedback below.