Applescript to get track number of song from multi-cd album in iTunes

applescriptitunes

I have an Applescript that reports the currently playing song name, album, song number, and total number of songs on the album. If the album comes from a single CD or if the song comes from CD 1 of a multi-CD album, everything works, and I get the following:

Song 2 of 30

However, if the album comes from a multi-CD set, then the song number is incorrect for songs from CD 2, CD 3, etc. Here's an example: L'Elisir d'Amore has two CDs, and in iTunes, it is entered as such (e.g., CD 1 of 2 and CD 2 of 2). The script correctly reports there are 30 songs (16 on CD 1 and 14 on CD 2). When playing a song from CD 1, everything is accurate. When playing a song from CD 2, the song number begins again at 1, so the very last song appears as

Song 14 of 30

because it is the 14th song on CD 2. Is there a way to get the script to display Song 30 of 30 for the last song on CD 2 without some kludge of figuring out the number of CDs, then counting up the songs in CD 1 and then adding to the track number of the song in CD 2? This kludge gets quite ugly for albums spanning as many as 14 CDs.

Here's the simplified bit of code:

tell application "iTunes"
    -- code to check that there is a current song
    set z_album to album of current track as string
    set z_num to count of (every track whose album is z_album)
    set z_song to name of current track as string
    set z_trk to track number of current track
    log z_song & " (" & z_trk & " of  " & z_num & ")"
end tell

Best Answer

Personally I do not have much of a need, if any, to automate iTunes with AppleScript. In the past I've found iTunes to be one of the more difficult apps to automate. Nonetheless, I took a look at your code, the AppleScript Dictionary for iTunes, a few web searches that basically yielded nothing noteworthy, and some failed programmatic attempts to easily get a list of discs and track count for each disc of an album.

I'll assume the kludge context in your question is because there is no easy direct way to programmatically ask an album for its disc count and track count per disc to do the math with, in a straight forward manner. So with that... here's my kludge, which was tested and works as desired on my iTunes Library:

tell application "iTunes"
    try

        set theCurrentTrackProperties to (properties of current track)

        if (disc number in theCurrentTrackProperties) is not greater than 1 then

            set theSongName to (name in theCurrentTrackProperties)
            set theTrackNumber to (track number in theCurrentTrackProperties)
            set theTrackCount to (track count in theCurrentTrackProperties)

            log theSongName & " (" & theTrackNumber & " of " & theTrackCount & ")"

        else

            set theSongName to (name in theCurrentTrackProperties)
            set theTrackNumber to (track number in theCurrentTrackProperties)
            set theTrackCount to (count of (every track whose album = (album in theCurrentTrackProperties)))

            set theDiscNumber to (disc number in theCurrentTrackProperties)
            set theAlbumsTracksProperties to (properties of every track whose album = (album in theCurrentTrackProperties))

            set theAlbumsDiscNumberTrackCountInfo to ""
            repeat with i from 1 to (count of theAlbumsTracksProperties)
                tell item i in theAlbumsTracksProperties
                    set theAlbumsDiscNumberTrackCountInfo to (theAlbumsDiscNumberTrackCountInfo & disc number & space & track count & linefeed)
                end tell
            end repeat
            tell current application
                set theAlbumsDiscNumberTrackCountInfo to (do shell script "sort -n -k1 -u <<<" & quoted form of theAlbumsDiscNumberTrackCountInfo & " | sed '/^$/d'")
                set theTracksPerDiscCount to ""
                repeat with i from 1 to (theDiscNumber - 1)
                    set theTracksPerDiscCount to (theTracksPerDiscCount + (word 2 of paragraph i in theAlbumsDiscNumberTrackCountInfo))
                end repeat
                set theTrackNumber to (theTrackNumber + theTracksPerDiscCount)
            end tell

            log theSongName & " (" & theTrackNumber & " of " & theTrackCount & ")"

        end if

    on error eStr number eNum
        display dialog eStr & " number " & eNum buttons {"OK"} default button 1 with icon caution
        return
    end try
end tell

The example AppleScript code, shown above, does the following:

  • Sets the properties of the current track to the variable theCurrentTrackProperties.
  • Checks to see if the value of the disc number property in the variable, theCurrentTrackProperties, is not greater than 1.
  • If the value of the disc number property is not greater than 1, it's straight forward processing and logs the desired information.
  • If the value of the disc number property is greater than 1, then the else branch preforms the kludge to do the math, and logs the desired information.

What the kludge does:

  • Sets some additional initial variables.
    • One for the value of the disc number property of the current track,theDiscNumber, is used to determine how many discs the track count is needed for.
    • Another to hold the properties of every track of every disc in the album, theAlbumsTracksProperties.
      • The value of the variable, theAlbumsTracksProperties, is processed in a repeat loop to which the output of is held in the variable theAlbumsDiscNumberTrackCountInfo.
  • The variable theAlbumsDiscNumberTrackCountInfo, is a list of the disc number and track count from every track in the album.
    • This list is then processed to remove all duplicate info, so as to have a singular entry for the track count of each disc number in the album.
  • The do shell script command uses sort and sed to process the list, the value of the variable theAlbumsDiscNumberTrackCountInfo.
    • sort -n -k1 -u <<<
      • -n compare according to string numerical value
      • -k1 start a key at POS1
      • -u without -c, output only the first of an equal run
      • <<< directs input from the command line, not a file
    • theAlbumsDiscNumberTrackCountInfo the list as command line input directed to sort
    • | sed '/^$/d'
      • | pipe the output of the sort command to sed
      • sed '/^$/d' delete blank lines
      • Because the value of the variable theAlbumsDiscNumberTrackCountInfo is a concatenation with a linefeed at the end of each repeat loop, it becomes the first line of output from the sort command and is removed with sed, so as not to have to account for the leading blank line later in the script. If it was left as a part of value of the variable theAlbumsDiscNumberTrackCountInfo, that's (re)set by the return of the do shell script command, then word 2 of paragraph i would have to be word 2 of paragraph (i + 1) in order to skip the leading blank line. So it makes more sense to remove it before it ends up as part of the final value of the variable theAlbumsDiscNumberTrackCountInfo.
  • With the variable, theAlbumsDiscNumberTrackCountInfo, now only containing a list of disk number with its corresponding track count, one line for each disc in the album, it's now easy to do the math, whether the album contains 2 discs or as many as 14 discs, or more.
  • The remaining AppleScript code, which includes another repeat loop, preforms the math necessary to add up the track count of each disc number preceding the disc number the current track is from, and adds them together, and then logs the desired information.

That said, if anyone knows an easy direct way to programmatically ask an album for its disc count and track count per disc to do the math with, in a straight forward manner to avoid a kludge, please post an answer.