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
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With