You should be automatically redirected . If not, visit
http://newlisper.wordpress.com
and update your bookmarks.

27/06/2008

iTunes covers by newLISP

The latest iPods and iPhones from Apple share an excellent user interface, but there's one area that I find difficult to use. Ironically, in the case of the iPod at least, it's the main screen you see while music's being played that's the problem. Consider this photograph:

photo of iPod Touch being unhelpful

It gives a reasonable impression of what the problems are. Unless your eyesight is good (mine isn't), and the lighting conditions are good (they often aren't), it's hard to read the three lines of text at the top - artist, title, and album. Two of these lines are drawn in grey on a black background. A lower-case 'a' in the chosen font measures just over 1 millimetre, or about 3 points. The large area in the middle of the display can show you the album artwork, but if there's no artwork you see two big quavers on a light grey background. What really needs to be provided is a customizable display, where you can specify what information is shown, and how it's presented. It would be nice if you could ask for a display that contains the main information in a larger font, and easier to read graphics.

But, I hear you say, what's all this got to do with newLISP?

You know the answer.

I couldn't resist trying to persuade iTunes to create substitute album artwork that shows the music's details in larger type as album art when it's downloaded to the iPod... I can use newLISP for most of the work. But, unfortunately, the easiest way to talk to iTunes on MacOS X is by using AppleScript, that quirky and devious language whose syntax was once described as "similar to English spelling - not thoroughly thought through".

So let's get the AppleScript stuff over first. Here's a good place to start: get the current selection from iTunes. The necessary AppleScript can be wrapped up in a newLISP function call:

(define (itunes-get-selection)
    (let ((result (exec 
             (format [text]osascript -s s -e 'tell application "iTunes" to get selection'[ /text]))))
         (set 'result (replace "{|}" (first result) "" 0))
         (parse result ", ")))

iTunes returns the information in an AppleScript list, which is easily changed into a newLISP list. Notice that extra '-s s' option flag in the osascript command. That appears to be significant. The result is a list of wordy track references (WTRs):

("file track id 15639 of user playlist id 13999 of source id 41 of application \"iTunes\"" 
 "file track id 15299 of user playlist id 13999 of source id 41 of application \"iTunes\"")

Given a WTR, it's possible to ask iTunes for more information about a track. As usual, I use the Unlikely Delimiter Ploy (UDP) when obtaining information from iTunes, mainly because iTunes track names can contain virtually any character. I've not yet seen four tildes used before, though, so I'm sticking with them for now:

(define (itunes-get-details-of-track file-track-id)
  (let ((result (exec 
            (format [text]osascript -s s -e 'tell application "iTunes"
              tell %s 
                set d to (name & "~~~~" & artist & "~~~~" & album & "~~~~" & duration & "~~~~" & year & "~~~~" & genre) as text
               end tell
             end tell '[ /text] file-track-id))))
      (when result           
         (set 'result 
             (transpose 
                (list '(track-name artist album duration year genre) 
                (parse (trim (first result) {"} {"}) "~~~~"))))
          result)))

That's such an ugly function! But it works:

((track-name "Maiden Voyage") 
 (artist "Herbie Hancock") 
 (album "An Evening With Herbie Hancock and Chick Corea - In Concert CD2") 
 (duration "810.840026855469") 
 (year "1978") 
 (genre "jazz"))

There's just one more piece of AppleScript required, to change the album artwork. Apple could have made this nice and easy:

set artwork of track to "some-artwork.jpg" -- this doesn't work :)

but they didn't. The required newLISP-wrapped code is this:

(define (itunes-set-data-of-artwork file-track-id)
   (exec (format [text]osascript -s s -e 'tell application "iTunes"
      delete every artwork of %s
      set the_artwork to read file (((path to desktop) as text) & "artwork-canvas.pict") from 513 as picture
      set data of artwork 1 of %s to the_artwork
    end tell'[ /text] file-track-id file-track-id )))

This looks for a graphic in PICT format at ~/Desktop/artwork-canvas.pict, strips the 512 byte header, loads the picture data, and applies the result to the track as album artwork.

I can't persuade newLISP-GS to produce PICT files, but luckily the Mac comes with the sips image processing tool, so converting PNG to PICT is easy.

(define (convert-to-pict file-name)
    (let ((new-file-name (replace {(.*)(\.)(.*$)} (string file-name) (string $1 ".pict") 1)))
          (exec (format "sips -s format pict '%s' --out '%s'"  file-name new-file-name))))

So now I can take off my AppleScripter's hat and switch to newLISP. To produce the graphics, I use a newLISP-GS canvas, after first setting up the graphics system:

(load (append (env "NEWLISPDIR") "/guiserver.lsp"))
(gs:init)
(gs:window 'Artwork 200 200 320 320)  
(gs:canvas 'ArtworkCanvas)
(gs:set-size 'ArtworkCanvas  320 320)
(gs:add-to 'Artwork 'ArtworkCanvas )
(gs:set-background 'ArtworkCanvas gs:gray)
(gs:set-visible 'Artwork true)

and then use commands such as set-font and draw-text to draw some more informative artwork. The main loop is simple enough, in theory at least:

(dolist (track (itunes-get-selection))
  (set 'data (itunes-get-details-of-track track))

  ; start drawing
  (gs:draw-text 'AlbumText (string (lookup 'artist data)) ...

  ; repeat for other information

  ; then:
  (gs:update)  

  (set 'temp-file (string "/Users/me/Desktop/" {artwork-canvas.png}))
  (gs:export temp-file)
  (convert-to-pict temp-file)
  (itunes-set-data-of-artwork track)

  ; delete all text
  (gs:delete-tag 'AlbumText)

  ; and start on the next one
  )

In practice there are various issues to address, such as timing - all these external processes appear to hamper a smoothly flowing script - so some sleep commands have to be added. Also, you might want to waste, I mean, spend more time adjusting the formatting and typography. I like adjusting the point size so that the line of type fits perfectly, and changing the colours to suit the genre. But that's another story!

some artwork

0 Comments:

Post a Comment

Links to this post:

Create a Link

<< Home