Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking iTunes' ITC2 files and "iTunesLibrary.XML"

Tags:

xml

image

itunes

I'm trying to dump album artwork from iTunes' .ITC2 files. Witch I can do. But before I try and dump the image, I need to make note of what Album/Track/Artist (any of the three) that it corresponds to. Has anyone found out if they changed the way the cache files are named? Because, with a file name of "2100F8A77FA24601-F2E26C349A9AB861.itc2" "2100F8A77FA24601" is in fact my Library ID but "F2E26C349A9AB861" is nowhere to be found in my Library's XML file. Can someone explain to me how to correlate itc2 files with tracks that are located in the XML file.

reference

I did get a little information about how iTunes is setup from the above link. But this post is outdated and not 100% correct to today's version of iTunes (v11).

Thanks, Throdne

like image 473
Throdne Avatar asked Dec 10 '12 06:12

Throdne


1 Answers

Well, actually, the second part of the .itc2 file name should be the track persistent id that is inside the iTunes Library.xml file. Perhaps you have the artwork cache for a deleted track?

The path to the artwork can be calculated from information retrieved from the XML library in this way:

[itunes library folder]/Album Artwork/Cache/[Library Persistent ID]/XX/YY/ZZ/[Library Persistent ID - Track Persistent ID].itc2

Where:

    XX: First hex digit from the end in the track persistent id in decimal form
    YY: Second hex digit from the end in the track persistent id in decimal form
    ZZ: Third hex digit from the end in the track persistent id in decimal form

So if:

Library Persistent ID = BEAE1DB35624CB18
Track Persistent ID = 2488665ADBC5420F

Then the folder is:

[itunes library folder]/Album Artwork/Cache/BEAE1DB35624CB18/15/00/02/BEAE1DB35624CB18-2488665ADBC5420F.itc2

The iTunes XML library uses the plist xml format, which is XML done wrong. Still, you can find your way thru with some XSLT sorcery.

Check the java code below, that will transform the iTunes Library.xml and put the calculated artwork path, alongside artist and track name in output.xml:

Test.java:

import java.io.File;

import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class Test {
    public static void main(String[] args) throws Exception {   
        String libraryFolder = "/Path/To/iTunes/";
        TransformerFactory factory = TransformerFactory.newInstance();
        Source xslt = new StreamSource(new File("convert.xsl"));
        Transformer transformer = factory.newTransformer(xslt);
        transformer.setParameter("library_folder", libraryFolder);
        Source text = new StreamSource(new File(libraryFolder + "iTunes Library.xml"));
        transformer.transform(text, new StreamResult(new File(libraryFolder  + "output.xml")));
    }
}

And convert.xsl:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:param name="library_folder"/>
    <xsl:template match="plist">
        <xsl:variable name="libid">
            <xsl:value-of select="dict/key[. = 'Library Persistent ID']/following-sibling::string[1]"/>
        </xsl:variable>
        <tracks>
            <xsl:apply-templates select="dict/key[. = 'Tracks']/following-sibling::dict[1]/dict" mode="track">
                <xsl:with-param name="libid"><xsl:value-of select="$libid"/></xsl:with-param>
            </xsl:apply-templates>
        </tracks>
    </xsl:template>

    <xsl:template match="dict" mode="track">  
        <xsl:param name="libid" />
        <entry>
            <xsl:variable name="trackid">
                <xsl:value-of select="key[. = 'Persistent ID']/following-sibling::string[1]"/>
            </xsl:variable>
            <xsl:variable name="dig1">
                <xsl:call-template name="HexToDecimal">
                    <xsl:with-param name="hexNumber" select="substring($trackid, string-length($trackid))"/>
                </xsl:call-template>
            </xsl:variable>
            <xsl:variable name="dig2">
                <xsl:call-template name="HexToDecimal">
                    <xsl:with-param name="hexNumber" select="substring($trackid, string-length($trackid) - 1, 1)"/>
                </xsl:call-template>
            </xsl:variable>
            <xsl:variable name="dig3">
                <xsl:call-template name="HexToDecimal">
                    <xsl:with-param name="hexNumber" select="substring($trackid, string-length($trackid) - 2, 1)"/>
                </xsl:call-template>
            </xsl:variable>
            <artist><xsl:value-of select="key[. = 'Artist']/following-sibling::string[1]"/></artist>
            <name><xsl:value-of select="key[. = 'Name']/following-sibling::string[1]"/></name>
            <track_id><xsl:value-of select="$trackid"/></track_id>
            <artwork><xsl:value-of select="concat($library_folder, 'Album Artwork/Cache/',$libid,'/',$dig1,'/',$dig2,'/',$dig3,'/',$libid,'-',$trackid,'.itc2')"/></artwork>
        </entry>
    </xsl:template>

    <!-- Very simple hex to decimal, only one digit -->
    <xsl:template name="HexToDecimal">
        <xsl:param name="hexNumber" />
        <xsl:value-of select="format-number(number(substring-before(substring-after('00/11/22/33/44/55/66/77/88/99/A10/B11/C12/D13/E14/F15/a10/b11/c12/d13/e14/f15/', $hexNumber), '/')),'00')" />
    </xsl:template>

</xsl:stylesheet>
like image 153
Mauricio Moura Avatar answered Oct 20 '22 23:10

Mauricio Moura