property prefs : missing value
property prefsPath : missing value
on get_tracklength(numBars, isUTF)
my loadPrefs()
if numBars is 0 then
-- just use regular time
tell application "iTunes"
set thePosition to my convertTime(player position)
if duration of current track is missing value then
set theDuration to "∞"
else
set theDuration to my convertTime(duration of current track)
end if
end tell
return "(" & thePosition & " / " & theDuration & ")"
else
tell application "iTunes"
if duration of current track is not missing value then
set n to round (player position / (duration of current track) * numBars)
else
set n to -1
end if
end tell
if isUTF then
set leftedge to "╞"
set bar to "═"
set marker to "╪"
set rightedge to "╡"
else
set leftedge to "["
set bar to "="
set marker to "|"
set rightedge to "]"
end if
set str to "" & leftedge
repeat with b from 0 to numBars
if b < n then
set str to str & bar
else if b = n then
set str to str & "" & marker & ""
else
set str to str & bar
end if
end repeat
set str to str & rightedge & ""
return str
end if
end get_tracklength
on convertTime(theTime)
set theMinutes to (theTime div 60) as string
set theSeconds to ((theTime mod 60 as integer) as string)
if length of theSeconds is 1 then
set theSeconds to "0" & theSeconds
end if
return theMinutes & ":" & theSeconds
end convertTime
on rgbStringOf(theColor)
repeat with i from 1 to 3
if item i of theColor < 256 then set item i of theColor to 256
if item i of theColor > 65270 then set item i of theColor to 65270
end repeat
set rtn to "rgb(" & (round ((item 1 of theColor) / 256 - 0.5)) & "," & (round ((item 2 of theColor) / 256 - 0.5)) & "," & (round ((item 3 of theColor) / 256 - 0.5)) & ")"
return rtn
end rgbStringOf
on encodeEntities(htmlText)
set oldDelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to the "&"
set the itemList to every text item of htmlText
set AppleScript's text item delimiters to the "&"
set htmlText to the itemList as string
set AppleScript's text item delimiters to the "<"
set the itemList to every text item of htmlText
set AppleScript's text item delimiters to the "<"
set htmlText to the itemList as string
set AppleScript's text item delimiters to the ">"
set the itemList to every text item of htmlText
set AppleScript's text item delimiters to the ">"
set htmlText to the itemList as string
set AppleScript's text item delimiters to the "\""
set the itemList to every text item of htmlText
set AppleScript's text item delimiters to the """
set htmlText to the itemList as string
set AppleScript's text item delimiters to the "'"
set the itemList to every text item of htmlText
set AppleScript's text item delimiters to the "'"
set htmlText to the itemList as string
set AppleScript's text item delimiters to oldDelims
return htmlText
end encodeEntities
on urlEncodeText(thisText, encodeGroupA, encodeGroupB)
set the acceptableCharacters to "abcdefghijklmnopqrstuvwxyz0123456789"
set the aCharacters to "$+!'/?;&@=#%><{}[]\"~`^\\|*"
set the bCharacters to ".-_:"
if encodeGroupA is false then ¬
set the acceptableCharacters to the acceptableCharacters & the aCharacters
if encodeGroupB is false then ¬
set the acceptableCharacters to the acceptableCharacters & the bCharacters
set the encodedText to ""
repeat with thisChar in thisText
if thisChar is in the acceptableCharacters then
set the encodedText to (the encodedText & thisChar)
else if thisChar is in " " then
set the encodedText to (the encodedText & "+")
else
set the encodedText to (the encodedText & urlEncodeCharacter(thisChar)) as string
end if
end repeat
return the encodedText
end urlEncodeText
on urlEncodeCharacter(thisChar)
set the asciiNumber to (the ASCII number thisChar)
set the hexList to {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}
set x to item ((asciiNumber div 16) + 1) of the hexList
set y to item ((asciiNumber mod 16) + 1) of the hexList
return ("%" & x & y) as string
end urlEncodeCharacter
on get_rating(the_track, EncodingIsUTF)
tell application "iTunes"
set the_rating to the rating of the_track
end tell
if the_rating is not missing value and the_rating is not equal to 0 then
tell application "iTunes"
if not (exists the rating of the_track) or the_rating is missing value then
return ""
else
set stars to (the_rating div 20) as integer
if the_rating is greater than 0 and stars is equal to 0 then
set stars to 1
end if
end if
end tell
if not EncodingIsUTF then return "(" & stars & " stars)"
set starString to "("
set fullstar to "✮"
set emptystar to "✩"
if stars is equal to 0 then
set starString to ""
repeat with i from 1 to 5
set starString to starString & emptystar
end repeat
set starString to starString & ""
else
repeat with i from 1 to stars
set starString to starString & fullstar
end repeat
repeat with i from stars to 4
set starString to starString & emptystar
end repeat
end if
set starString to starString & ")"
return starString
else
return ""
end if
end get_rating
using terms from application "Colloquy"
on process user command c with arguments for view
if c is in {"itunes", "music"} then
try
tell application "System Events"
set itunesRunning to ((application processes whose name is equal to "iTunes") count) is greater than 0
end tell
if (arguments is "" or arguments is missing value) then
set theitunes to my getitunes(encoding of view is UTF8)
if theitunes is "not running" then
set msg to "isn't running iTunes currently."
else if theitunes is "paused" then
set msg to "has iTunes paused."
else if theitunes is "unknown track type" then
set msg to "is listening to an unknown type of track."
else
set msg to "is listening to " & theitunes
end if
tell view to send message msg with action tense
else if first word of arguments is "open" then
ignoring application responses
tell application "iTunes" to activate
end ignoring
else if first word of arguments is "quit" and itunesRunning then
ignoring application responses
tell application "iTunes" to quit
end ignoring
else if first word of arguments is "play" then
ignoring application responses
tell application "iTunes" to play
end ignoring
else if first word of arguments is "pause" and itunesRunning then
ignoring application responses
tell application "iTunes" to pause
end ignoring
else if first word of arguments is "stop" and itunesRunning then
ignoring application responses
tell application "iTunes" to stop
end ignoring
else if first word of arguments is "next" and itunesRunning then
ignoring application responses
tell application "iTunes" to next track
end ignoring
else if first word of arguments is "previous" and itunesRunning then
ignoring application responses
tell application "iTunes" to previous track
end ignoring
else if first word of arguments is "rating" and itunesRunning then
set EncodingIsUTF to (encoding of view is UTF8)
--if the command is just "/itunes rating", this try block will cause an error in the first line, skip the rest of the block, and no one will be the wiser. Otherwise, it will set the rating then continue the script.
try
set theRating to (word 2 of arguments) as number
tell application "iTunes"
if player state is playing then
set rating of current track to theRating * 20
end if
end tell
end try
tell application "iTunes"
if player state is playing then
set starString to my get_rating(current track, EncodingIsUTF)
set msg to "iTunes song rating: " & starString
set actionTense to false
else
set msg to "has iTunes paused"
set actionTense to true
end if
end tell
if actionTense then
tell view to send message msg with action tense
else
tell view to send message msg
end if
else if first word of arguments is "stats" and itunesRunning then
try
set args to words 2 through -1 of arguments
on error
set args to ""
end try
tell view to send message "'s " & my getStats(args) with action tense
else if first word of arguments is "prefs" then
tell view to add event message "Control-click (or right-click) here for iTunes Prefs" with name "itunes"
return true
end if
return true
on error err
display dialog err
end try
else if c is "reload" then
if arguments is "prefs" then
my reloadprefs()
end if
return false
end if
return false
end process user command
(* on process incoming chat message m
my loadPrefs()
if prefs's getKey("Link Songs") is in {missing value, false} then
return m
end if
if body of m starts with "is listening to " and action tense of m is true and prefs's getKey("Link Songs") is true then
set segments to attribute run of m
if (count of segments) ≥ 3 and item 1 of segments is "is listening to " then
try
set theSong to item 2 of segments
set theArtist to missing value
if (count of segments) is greater than or equal to 4 and item 3 of segments is equal to " by " then set theArtist to item 4 of segments
set theAlbum to missing value
if (count of segments) is greater than or equal to 6 and item 5 of segments is equal to " from " then set theAlbum to item 6 of segments
if (count of segments) is greater than or equal to 4 and item 3 of segments is equal to " from " then set theAlbum to item 4 of segments
set initialSearch to "itms://phobos.apple.com/WebObjects/MZSearch.woa/wa/advancedSearchResults?"
set artistSearch to initialSearch
set albumSearch to initialSearch
set delim to ""
if theArtist is not missing value then
set artistSearch to artistSearch & "artistTerm=" & my urlEncodeText(theArtist, true, true)
set albumSearch to artistSearch
set delim to "&"
set link of attribute run 4 of m to artistSearch
set style classes of attribute run 4 of m to {"itunes"}
end if
if theAlbum is not missing value then
set albumSearch to albumSearch & delim & "albumTerm=" & my urlEncodeText(theAlbum, true, true)
set delim to "&"
if theArtist is missing value then
set albumIndex to 4 --which attribute is the album string
else
set albumIndex to 6
end if
set link of attribute run albumIndex of m to albumSearch
set style classes of attribute run albumIndex of m to {"itunes"}
end if
set songSearch to albumSearch & delim & "songTerm=" & my urlEncodeText(theSong, true, true)
set link of attribute run 2 of m to songSearch
set style classes of attribute run 2 of m to {"itunes"}
on error err
display dialog err
end try
end if
end if
end process incoming chat message *)
on build contextual menu for item theItem
try
if theItem contains "listening" then
my loadPrefs()
tell prefs to set sm to getContextMenu()
return {title:"iTunes Script Settings", submenu:sm}
end if
on error err
-- return {title:"iTunes script got an error!!", submenu:{{title:err, enabled:false}, {title:build of prefs as string}}}
end try
end build contextual menu for item
on handle clicked contextual menu item theItem within theParents
if theParents is {"iTunes Script Settings"} then
try
prefs's changekey(theItem)
my savePrefs()
on error err
display dialog err
end try
end if
end handle clicked contextual menu item
end using terms from
script prefsTemplate
property defaultKeys : {¬
{label:"Show Rating", value:true}, ¬
{label:"Show Colors", value:true}, ¬
{label:"Link Songs", value:true}, ¬
{label:"Show Time", value:false}, ¬
{label:"Show Progress Bar", value:false}, ¬
{label:"--Left Progress Bar Color", value:{40000, 40000, 40000}}, ¬
{label:"--Progress Bar Marker Color", value:{40000, 40000, 40000}}, ¬
{label:"--Right Progress Bar Color", value:{40000, 40000, 40000}}, ¬
{label:"Show Bit Rate", value:false} ¬
}
property theKeys : defaultKeys
property build : 10 --increment each time you change something where prefs needs to change
--returns true if the value was found, false if the value had to be created
on setKey(thisLabel, newValue)
repeat with k in theKeys
if label of k is thisLabel then
set value of k to newValue
return true
end if
end repeat
set theKeys to theKeys & {{label:thisLabel, value:newValue}}
return false
end setKey
--like setKey, except it handles the interface: if it's boolean it toggles it, if it's a string it will ask for a new value, etc
on changekey(thisLabel)
set asd to AppleScript's text item delimiters
set AppleScript's text item delimiters to " ("
set thisLabel to text item 1 of thisLabel
set oldvalue to getKey(thisLabel)
set AppleScript's text item delimiters to asd
if oldvalue is missing value then
display dialog "That item (" & thisLabel & ") does not exist"
return
else if class of oldvalue is boolean then
setKey(thisLabel, not oldvalue)
else if class of oldvalue is string then
set ans to (text returned of (display dialog "New value?" default answer oldvalue) as string)
setKey(thisLabel, ans)
else if class of oldvalue is integer then
set ans to text returned of (display dialog "New value?" default answer oldvalue)
setKey(thisLabel, ans as integer)
else if class of oldvalue is list then
if number of items in oldvalue is 3 then ---must be a color
set ans to choose color default color oldvalue
setKey(thisLabel, ans)
else
display dialog "Cannot edit lists of items."
end if
end if
end changekey
on getKey(thisLabel)
repeat with k in theKeys
if label of k is thisLabel then
return value of k
end if
end repeat
return missing value
end getKey
on listKeys()
set final to ""
repeat with k in theKeys
set final to final & label of k & ": " & (value of k as string) & return
end repeat
return final
end listKeys
on getContextMenu()
set final to {}
try
repeat with k in theKeys
if class of value of k is boolean then
set final to final & {{title:label of k, checked:value of k}}
else if class of value of k is integer or class of value of k is string then
set final to final & {{title:label of k & " (" & value of k & ")"}}
else if class of value of k is list then
set asd to AppleScript's text item delimiters
set AppleScript's text item delimiters to ", "
if number of items in value of k < 3 then
set final to final & {{title:label of k & " (" & (every item of value of k as string) & ")"}}
else if number of items in value of k is 3 then
set final to final & {{title:label of k, icon:value of k}}
else
set final to final & {{title:label of k & " (" & (items 1 through 3 of value of k as string) & ", ...)"}}
end if
set AppleScript's text item delimiters to asd
end if
end repeat
return final
on error err
return {{title:"iTunes script got an error: " & err, enabled:false}}
end try
end getContextMenu
end script
on loadPrefs()
if prefs is missing value then
set prefsPath to (path to preferences folder from user domain as Unicode text) & "Colloquy Prefs - iTunes"
try
set prefs to load script alias prefsPath
try
set oldbuild to build of prefs
on error
set oldbuild to -1
end try
if oldbuild < build of prefsTemplate then
set newPrefs to prefsTemplate
set newPrefs to my mergeKeys(prefs, prefsTemplate)
set prefs to newPrefs
my savePrefs()
end if
on error
set prefs to prefsTemplate
end try
end if
end loadPrefs
on savePrefs()
if prefs is not missing value then store script prefs in file prefsPath replacing yes
end savePrefs
--This function is used to merge keys of the old list with the values of the new one.
--Note that the first parameter is the old version of the prefs (from which the values need to be kept), and the second contains the new list (with default values to be overwritten by values gotten from oldPrefs
--returns the list to set theKeys to
on mergeKeys(oldPrefs, newDefaultPrefs)
try
repeat with k in theKeys of newDefaultPrefs
set oldvalue to oldPrefs's getKey(label of k)
if oldvalue is not missing value then
set value of k to oldvalue
end if
end repeat
end try
return newDefaultPrefs
end mergeKeys
on getitunes(EncodingIsUTF)
tell application "System Events"
set itunesRunning to ((application processes whose name is equal to "iTunes") count) is greater than 0
end tell
if itunesRunning then
tell application "iTunes"
if player state is playing then
return item 1 of my getitunesFor(EncodingIsUTF, current track)
else
return "paused"
end if
end tell
else
return "not running"
end if
end getitunes
on getitunesFor(EncodingIsUTF, trackID)
tell application "System Events"
set itunesRunning to ((application processes whose name is equal to "iTunes") count) is greater than 0
end tell
set fullmsg to {}
if itunesRunning then
my loadPrefs()
tell application "iTunes"
if class of trackID is not list then set trackID to {trackID}
repeat with thisTrackID in trackID
if class of thisTrackID is integer then
set thisTrack to (first track of library playlist 1 whose database ID is thisTrackID)
else if class of thisTrackID is in {track, file track, URL track, device track, shared track, audio CD track} then
set thisTrack to thisTrackID
else
error "Unknown class" number 3245
end if
if class of thisTrack is in {track, file track, URL track, device track, shared track, audio CD track} then
if class of thisTrack is URL track then
set theSong to current stream title
if theSong is missing value then
set theSong to name of thisTrack
set theAlbum to missing value
else
set theAlbum to name of thisTrack
end if
set theArtist to missing value
else
set theArtist to artist of thisTrack
set theAlbum to album of thisTrack
set theSong to name of thisTrack
end if
set showColors to prefs's getKey("Show Colors")
if showColors then
set msg to "" & my encodeEntities(theSong) & ""
else
set msg to my encodeEntities(theSong)
end if
if theArtist is not "" and theArtist is not missing value then
if showColors then
set msg to msg & " by " & my encodeEntities(theArtist) & ""
else
set msg to msg & " by " & my encodeEntities(theArtist)
end if
end if
if theAlbum is not "" and theAlbum is not missing value then
if showColors then
set msg to msg & " from " & my encodeEntities(theAlbum) & ""
else
set msg to msg & " from " & my encodeEntities(theAlbum)
end if
end if
if prefs's getKey("Show Rating") then
set msg to msg & " " & my get_rating(thisTrack, EncodingIsUTF)
end if
if prefs's getKey("Show Time") then
set msg to msg & " " & my get_tracklength(0, EncodingIsUTF)
end if
if prefs's getKey("Show Progress Bar") then
set msg to msg & " " & my get_tracklength(10, EncodingIsUTF)
end if
if prefs's getKey("Show Bit Rate") then
set theKind to kind of thisTrack
if theKind contains "MPEG" then set theKind to "MP3"
if theKind contains "AAC" then set theKind to "AAC"
if theKind contains "WAV" then set theKind to "WAV"
if theKind contains "Apple Lossless" then set theKind to "Apple Lossless"
set msg to msg & " (" & bit rate of thisTrack & " kbps " & theKind & ")"
end if
else
set msg to "unknown track type"
end if
set fullmsg to fullmsg & {msg}
end repeat
end tell
end if
return fullmsg
end getitunesFor
on getStats(args)
tell application "iTunes"
if args is "" then
set lib to library playlist 1
set libName to name of library playlist 1
else
try
set lib to some playlist whose name contains args
set libName to "Playlist \"" & name of (some playlist whose name contains args) & "\""
on error
set lib to ""
end try
end if
if lib ≠ "" then
if size of lib < 1.0E+9 then
set mysize to (round (size of lib) / 1024 / 1024 * 100 as string) / 100 & " MB"
else
set mysize to ((round (size of lib) / 1024 / 1024 / 1024 * 100) / 100 as string) & " GB"
end if
set res to "iTunes " & libName & " is " & time of lib & " long, with " & (count tracks in lib) & " songs totalling " & mysize & "."
else
set res to ""
end if
end tell
if res ≠ "" then
return res
end if
end getStats