Initially I developed this script for a Majorcan disco owner who wanted to show cover art with a video projector, but after finishing Lacurne I slightly modified it to create and set a customizable PDF wallpaper on your desktop that shows random iTunes cover art.
Once again, the raw image and PDF processing is done with Python and its Quartz 2D bindings while the GUI, Finder interaction and preferences management is handled by AppleScript. Together this makes for a very efficient and convenient Mac automation solution.
The script allows to adjust the maximum cover width and height, let’s you set a foreground color and a color tint and can reduce the file size of the created PDF wallpaper by applying a Quartz filter.
Of course I invite you to download and inspect this free little AppleScript, but please don’t expect a polished application this time It’s still beta software (nevertheless it works just fine on all my private and company Macs):
Coverlover - A customizable PDF wallpaper showing random iTunes cover art on your desktop (v0.2, ca. 114.7 KB)
Coverlover requires Mac OS X 10.5 Leopard and iTunes 7. It was successfully tested on Intel and PowerPC based Macs, but runs significantly faster on Intel Macs.
To create and set a PDF wallpaper just open the script with a double click. If you want to open the configuration menu, then just drag and drop a Finder item onto the script’s icon:
Please note, that you won’t instantly see the changes made in the configuration menu. The new settings will only show up after you run Coverlover once again, as it will then create and set a new PDF document according to the chosen options.
Coverlover currently assumes that your iTunes folder containing ITC cover art files is located here:
~/Music/iTunes/Album Artwork/
The preferences are currently saved inside Coverlover’s script bundle.
If you are interested in the Python code that generates the PDF wallpaper, you can study it right here.
Important: Opening and saving the below script code in Script Editor won’t result in a usable AppleScript! That is because Coverlover internally relies on several scripts, which are located inside its Script bundle. Therefor please download the complete script here.
-- created: 07.06.2008
-- version: 0.1
-- requires:
-- ¢ Mac OS X 10.5 Leopard & iTunes 7
-- tested on:
-- ¢ Intel & PowerPC based Macs
-- notes:
-- ¢ runs a lot faster on an Intel based Mac
-- ¢ dual monitor setups are currently not supported
-- This AppleScript creates and sets a PDF wallpaper made of random iTunes cover art according to the chosen options.
-- To enter the configuration menu, just drop Finder items onto the script's icon.
property mytitle : "Coverlover"
-- I am called when the user drops Finder items onto the script's icon.
-- I am displaying the configuration menu and managing the preferences.
on open finderitems
repeat
set chosenmenuitem to my dspmainmenu()
if chosenmenuitem begins with "Set cover width" then
set coverwidth to my askforcoversize("width")
if coverwidth is not missing value then
my savepref("coverwidth", coverwidth)
end if
else if chosenmenuitem begins with "Set cover height" then
set coverheight to my askforcoversize("height")
if coverheight is not missing value then
my savepref("coverheight", coverheight)
end if
else if chosenmenuitem is "Set foreground color" then
set fgcolor to my askforfgcolor()
if fgcolor is not missing value then
my savepref("fgcolor", fgcolor)
end if
else if chosenmenuitem is "Deactivate foreground color" then
my savepref("fgcolor", missing value)
else if chosenmenuitem begins with "Set foreground color tint" then
set colortint to my askforcolortint()
if colortint is not missing value then
my savepref("colortint", colortint)
end if
else if chosenmenuitem is "Enable file size reduction" then
my savepref("quartzfilter", true)
else if chosenmenuitem is "Disable file size reduction" then
my savepref("quartzfilter", false)
else if chosenmenuitem is missing value then
exit repeat
end if
end repeat
end open
-- I am called when the user opens the script with a double click on its icon.
-- I am trying to create the wallpaper made of iTunes cover art.
on run
try
-- loading the preferences script object
set prefs to my loadprefs()
if prefs is missing value then
set errmsg to "Could not load the preferences script located inside my script bundle."
my dsperrmsg(errmsg, "--")
return
end if
-- preparing the preferences, so that they can be passed as
-- string arguments to the Python script
set coverwidth to (prefs's coverwidth) as Unicode text
set coverheight to (prefs's coverheight) as Unicode text
set fgcolor to prefs's fgcolor
if fgcolor is missing value then
set fgcolor to quoted form of "missing value"
else
set {redval, greenval, blueval} to prefs's fgcolor
-- replacing commas with points in float values, as
-- Python only accepts a point as decimal separator
set redval to my searchnreplace(",", ".", redval as Unicode text)
set greenval to my searchnreplace(",", ".", greenval as Unicode text)
set blueval to my searchnreplace(",", ".", blueval as Unicode text)
set fgcolor to redval & space & greenval & space & blueval
end if
set colortint to my searchnreplace(",", ".", (prefs's colortint as Unicode text))
set quartzfilter to (prefs's quartzfilter) as Unicode text
-- creating the shell command calling the Python script with the
-- corresponding arguments
set pyscriptpath to (((path to me) as Unicode text) & "Contents:Resources:Scripts:coverlover.py")
set command to "/usr/bin/python " & quoted form of POSIX path of pyscriptpath & " " & coverwidth & " " & coverheight & " " & fgcolor & " " & colortint & " " & quartzfilter
set shellresult to paragraphs of (do shell script command)
-- maybe there was an error...
if item 1 of shellresult begins with "Error:" then
set errmsg to ((characters 8 through -1 of (item 1 of shellresult)) as Unicode text)
my dsperrmsg(errmsg, "--")
return
end if
-- PDF wallpaper successfully created?
set pdffilepath to (((path to application support folder from user domain) as Unicode text) & "Coverlover:coverlover.pdf")
if not itempathexists(pdffilepath) then
set errmsg to "The PDF wallpaper could not be created."
my dsperrmsg(errmsg, "--")
return
end if
-- file path to the PNG image used as an update helper: if you try to update the desktop picture and
-- the file path of your new image is the same as the current one, you won't see
-- the new image. therefor we first «switch» to the small PNG image before updating
-- the wallpaper.
set switchfilepath to (((path to me) as Unicode text) & "Contents:Resources:switch.png")
tell application "Finder"
set desktop picture to (switchfilepath as alias)
end tell
delay 0.25
tell application "Finder"
set desktop picture to (pdffilepath as alias)
end tell
-- catching unexpected errors
on error errmsg number errnum
my dsperrmsg(errmsg, errnum)
end try
end run
-- I am displaying the configuration menu and return the chosen menu item.
-- In case the user cancels I return «missing value».
on dspmainmenu()
-- loading the preferences script object
set prefs to my loadprefs()
if prefs is missing value then
set errmsg to "Could not load the preferences script located inside my script bundle."
my dsperrmsg(errmsg, "--")
return missing value
end if
set micoverwidth to "Set cover width (" & prefs's coverwidth & "px)"
set micoverheight to "Set cover height (" & prefs's coverheight & "px)"
set micolortint to "Set foreground color tint (" & prefs's colortint & ")"
set menuitems to {micoverwidth, micoverheight, "Set foreground color", "Deactivate foreground color", micolortint, "Enable file size reduction", "Disable file size reduction"}
choose from list menuitems with title mytitle OK button name "Select" cancel button name "Quit" with prompt "Please choose an option" without multiple selections allowed and empty selection allowed
set usrchoice to result
if usrchoice is not false then
return item 1 of (usrchoice as list)
else
return missing value
end if
end dspmainmenu
-- I am loading the preferences script object and return it.
-- In case of an error I return «missing value».
on loadprefs()
set prefsfilepath to (((path to me) as Unicode text) & "Contents:Resources:Scripts:prefs.scpt")
try
set prefs to load script (prefsfilepath as alias)
return prefs
on error
return missing value
end try
end loadprefs
-- I am saving the chosen preferences to a script file
on savepref(prefkey, prefvalue)
set prefsfilepath to (((path to me) as Unicode text) & "Contents:Resources:Scripts:prefs.scpt")
set prefs to load script (prefsfilepath as alias)
if prefkey is "coverwidth" then
set prefs's coverwidth to prefvalue
else if prefkey is "coverheight" then
set prefs's coverheight to prefvalue
else if prefkey is "fgcolor" then
set prefs's fgcolor to prefvalue
else if prefkey is "colortint" then
set prefs's colortint to prefvalue
else if prefkey is "quartzfilter" then
set prefs's quartzfilter to prefvalue
end if
store script prefs in (prefsfilepath as alias) replacing yes
end savepref
-- I am asking the user to provide the maximum cover width/height and return the integer value.
-- In case the user cancels I return «missing value».
on askforcoversize(mode)
set dlgmsg to "Please enter the maximum cover " & mode & " as an integer:"
try
display dialog dlgmsg default answer "" buttons {"Cancel", "Enter"} default button 2 with title mytitle
on error
-- User canceled
return missing value
end try
set dlgresult to result
set usrinput to text returned of dlgresult
-- the user did not enter anything...
if usrinput is "" then
my askforcoversize(mode)
else
-- let's check if the user entered numbers only
set nums to {"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}
set invalidchars to ""
repeat with char in usrinput
if char is not in nums then
set invalidchars to invalidchars & char & space
end if
end repeat
-- we found invalid characters
if invalidchars is not "" then
set errmsg to "We found the following characters in the given input. Please enter numbers only." & return & return & invalidchars & return
my dsperrmsg(errmsg, "--")
my askforcoversize(mode)
else
-- let's try to transform the user input into an integer
try
set intvalue to usrinput as integer
return intvalue
on error
set errmsg to "We could not coerce the given input into an integer:" & return & return & usrinput & return
my dsperrmsg(errmsg, "--")
my askforcoversize(mode)
end try
end if
end if
end askforcoversize
-- I am asking the user to choose a color.
-- In case the user cancels I return «missing value».
on askforfgcolor()
try
set chosencolor to choose color
on error
return missing value
end try
set {redval, greenval, blueval} to chosencolor
set redval to redval / 65535
set greenval to greenval / 65535
set blueval to blueval / 65535
return {redval, greenval, blueval}
end askforfgcolor
-- I am asking the user to choose a tint value to highlight the last and next month
on askforcolortint()
set decseparator to my getdecseparator()
set dlgmsg to "Please choose a tint value used for the foreground color:" & return & "(value must be between 0 and 1," & return & "decimal separator: «" & decseparator & "»)"
try
tell me
activate
display dialog dlgmsg default answer "" buttons {"Cancel", "Enter"} default button 2 with title mytitle
end tell
set dlgresult to result
on error
return missing value
end try
set usrinput to text returned of dlgresult
if usrinput is "" then
my askforcolortint()
else
set usrinputisnum to true
try
set usrinput to usrinput as number
on error
set usrinputisnum to false
end try
if usrinputisnum is false then
set errmsg to "The entered value could not be coerced into a number."
my dsperrmsg(errmsg, "--")
my askforcolortint()
else
if usrinput < 0 or usrinput > 1 then
set errmsg to "The entered value is less than 0 or greater than 1."
my dsperrmsg(errmsg, "--")
my askforcolortint()
else
return usrinput
end if
end if
end if
end askforcolortint
-- I am returning the currently used decimal separator
on getdecseparator()
set strnum to 0.1 as Unicode text
set decseparator to character 2 of strnum
return decseparator
end getdecseparator
-- I am a very old search & replace function...
on searchnreplace(searchstr, replacestr, txt)
considering case, diacriticals and punctuation
if txt contains searchstr then
set olddelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to {searchstr}
set txtitems to text items of txt
set AppleScript's text item delimiters to {replacestr}
set txt to txtitems as Unicode text
set AppleScript's text item delimiters to olddelims
end if
end considering
return txt
end searchnreplace
-- I am indicating if a given item path exists or not
on itempathexists(itempath)
try
set itemalias to itempath as alias
return true
on error
return false
end try
end itempathexists
-- I am displaying error messages to the user
on dsperrmsg(errmsg, errnum)
tell me
activate
display dialog "Sorry, an error occured:" & return & return & errmsg & return & "(" & errnum & ")" buttons {"OK"} default button 1 with icon stop giving up after 20 with title mytitle
end tell
end dsperrmsg