Wallpaper Mavericks…

I have finally had enough of Mavericks’ shenanigans when it comes to Desktop Wallpapers…

For those not in the know, in OS X Mavericks, Apple has changed the mechanism for configuring Desktop Wallpaper from the venerable .plist to using a Sqlite3 database.

While using the database is probably more robust and easier to integrate, it is not as easy to change the desktop or, even more important from my perspective, to change all your desktops to the same wallpaper.

After some Googling and digging, I finally came up with the following little Python script which I called, reasonably enough, changewall:

#!/usr/bin/python

from __future__ import print_function

import os, sys, subprocess
import sqlite3

if len( sys.argv ) < 2:
    sys.exit( 'Usage: "%s" file-name' % sys.argv[ 0 ] )

if not os.path.exists( sys.argv[1] ):
    sys.exit( 'ERROR: File "%s" was not found!' % sys.argv[ 1 ] )

desktop_picture_path = sys.argv[ 1 ]
database_location = os.path.expanduser( '~/Library/Application Support/Dock/desktoppicture.db' )

conn = sqlite3.connect( database_location )
print( 'Opened database', end=", " )

cur = conn.cursor()
cur.execute( 'SELECT count( DISTINCT display_id ) + 1 FROM pictures;' )
displays = cur.fetchone()[0]

cur.execute( 'SELECT count( DISTINCT space_id ) + 1 FROM pictures;' )
spaces = cur.fetchone()[0]

conn.execute( 'DELETE FROM preferences' )

conn.execute( 'DELETE FROM data' )
conn.execute( 'INSERT INTO data VALUES (?)', ( desktop_picture_path, ))
conn.execute( 'VACUUM data' )

screens = spaces * displays
for screen in range( screens ):
    conn.execute( 'INSERT INTO preferences VALUES (1,1,?)', ( screen + 1, ))
    conn.execute( 'VACUUM preferences' )

conn.commit()

print( 'Records created successfully', end=", " )
conn.close()
print( 'Closed database' )

subprocess.check_call( ['/usr/bin/killall', 'Dock'] )

Not all that impressive, I’m fully aware, but it does seem to do the job. Using it is simplicity itself: changewall ~/Wallpaper/funky_wallpaper.jpg

As usual, do with it what you will…

Geektool is even cooler than I thought…

Hacking away at Geektool I decided to try something else: sending raw terminal escape-codes at it and see how it handled it… In short: even better than I thought. So here is an update to my earlier Geeklet to display a calendar:

ESC="\\\033["; \
printf "\n$( cal| \
    sed "\
        s/^/ /; s/$/ /;\
        /^ Su.*/d;\
        /.*$( date +'%B %Y' ).*/d;\
        /^$/d;\
        s/$( date +%e ) /${ESC}1;37m$( date +%e )${ESC}0m /g;\
    "\
)\n"

I will admit to still using the previous version, though, since I prefer the font bolding in that one.

Of fortunes and Macs and (Xscreen) savers…

Every so often I have the urge to do something quite unnatural; something like, for instance, actually updating the software on my Macbook…

Rather subversive, I know, but we all have our weaknesses.

One go the packages I make a habit of installing, and updating, is JWZ’s Mac build of Xscreensaver. The biggest down-side of doing that, though, is that, unlike in Linux, it doesn’t by default display quotes from the fortune files.

The ability do so is, of course, still very much there, but the Mac build does not have an easy way of enabling it.

Herewith, then, my workflow to get things back to “sanity” once I’ve upgraded.

Firstly, make sure that you have installed fortune from the ports (or any other way that takes your fancy):

eroux@smaug:~$ sudo port install fortune
--->  Fetching archive for fortune
--->  Fetching fortune
--->  Verifying checksum(s) for fortune
--->  Extracting fortune
--->  Applying patches to fortune
--->  Configuring fortune
--->  Building fortune
--->  Staging fortune into destroot
--->  Installing fortune @6.2.0-RELEASE_0+universal
--->  Activating fortune @6.2.0-RELEASE_0+universal
--->  Cleaning fortune
eroux@smaug:~$ 

Once you can run fortune and get a result, you are ready to continue:

eroux@smaug:~$ fortune
I always had a repulsive need to be something more than human.
                                                -- David Bowie
eroux@smaug:~$ type fortune
fortune is hashed (/opt/local/bin/fortune)
eroux@smaug:~$

Now you need the following patch, which we’ll use to convince Xscreensaver that we know what we’re doing:

--- xscreensaver-text.pre   2011-03-01 18:06:46.000000000 +0200
+++ xscreensaver-text       2011-03-01 18:07:05.000000000 +0200
@@ -247,6 +247,7 @@
   elsif ($text_mode eq '1') { $text_mode = 'literal'; }
   elsif ($text_mode eq '2') { $text_mode = 'file';    }
   elsif ($text_mode eq '3') { $text_mode = 'url';     }
+  elsif ($text_mode eq '4') { $text_mode = 'program'; }

   $v = get_cocoa_pref_1 ($id, "textLiteral");
   $text_literal = $v if defined ($v);

All we’re doing here is adding a program text mode to Xscreensaver, which we will then use via defaults to get fortune to run under its auspices.

Now we need to update all the files that actually could use some fortune:

for I in Apple2 FlipText FontGlide NoseGuy Phosphor StarWars XMatrix; do
    cd "/Library/Screen Savers/${I}.saver/Contents/Resources/" && 
        patch -p0 < ~/xscreensaver-text.patch && cd;
done

Now we get to test one of the screen savers. My favourite is one called Phosphor, so lets start with that:

defaults -currentHost write \
  org.jwz.xscreensaver.Phosphor \
  textProgram "/opt/local/bin/fortune";

This tells Phosphor which program to run, but not yet that it should actually use it. Let’s do that now, why don’t we?

defaults -currentHost write \
  org.jwz.xscreensaver.Phosphor \
  textMode 4;

Here you see us actually using the mode we defined in the patch, earlier. I had to change the scale of the fonts to get the display to fit on my screen, so if it’s too big or too small, you can change that from within the screensaver configuration window.

eroux@smaug:~$ defaults -currentHost read org.jwz.xscreensaver.Phosphor
{
    scale = 3;
    textMode = 4;
    textProgram = "/opt/local/bin/fortune";
}
eroux@smaug:~$

All done… Now you just need to sit back and wait for your screen to lock… Or just press Ctrl-Shift-Eject if you’re too impatient, of course.

Some alternatives to consider: Since the fortune you run is the same program you would find on any Linux machine, you could use “/opt/local/bin/fortune -s” to get only the short quotes, if you wish, or even “/opt/local/bin/fortune -o” for some… other quotes.