- 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 "<b>|</b>"
- set rightedge to "]"
- end if
- set str to "<span style=\"color:" & my rgbStringOf(prefs's getKey("--Left Progress Bar Color")) & "\">" & 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 & "</span><span style=\"color:" & my rgbStringOf(prefs's getKey("--Progress Bar Marker Color")) & "\">" & marker & "</span><span style=\"color:" & my rgbStringOf(prefs's getKey("--Right Progress Bar Color")) & "\">"
- else
- set str to str & bar
- end if
- end repeat
- set str to str & rightedge & "</span>"
- 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 "<font color=\"grey\">"
- repeat with i from 1 to 5
- set starString to starString & emptystar
- end repeat
- set starString to starString & "</font>"
- 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 "<a href=\"listening\">Control-click (or right-click) here for iTunes Prefs</a>" 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 "<font color=\"maroon\">" & my encodeEntities(theSong) & "</font>"
- 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 <font color=\"green\">" & my encodeEntities(theArtist) & "</font>"
- 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 <font color=\"teal\">" & my encodeEntities(theAlbum) & "</font>"
- 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