Sign In/My Account | View Cart  
advertisement


Listen Print Discuss

Hacking iTunes
by Niel Bornstein | Pages: 1, 2

Playlists

You can use XSLT to get a list of all of the playlists in your library.


<?xml version="1.0"?>
<xsl:stylesheet version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="text" />

  <xsl:variable name="newline">
<xsl:text>
</xsl:text>
  </xsl:variable>

  <xsl:template match="/">
    <xsl:for-each select="plist/dict/key[text()='Playlists']/ \
following-sibling::array/dict">
      <xsl:value-of select="key[text()='Name']/ \
following-sibling::string" /><xsl:value-of select="$newline" />
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

You can transform the playlists from the Music Library into other formats using XSLT. For example, the WinAmp playlist formats, documented at forums.winamp.com/showthread.php?threadid=65772, can be generated through an XSLT transform.

The M3U format is a simple text file listing directories and file names separated by a hyphen. The following stylesheet transforms a named iTunes playlist into a M3U playlist with the same name:


<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="text" />

  <xsl:param name="playlist" />

  <xsl:variable name="newline">
<xsl:text>
</xsl:text>
  </xsl:variable>

  <xsl:template match="/">
    <xsl:for-each select="plist/dict/key[text()='Playlists']/ \
following-sibling::array/dict/key[text()='Name']/ \
following-sibling::string[text()=$playlist]/ \
following-sibling::key[text()='Playlist Items']/ \
following-sibling::array/dict">
      <xsl:call-template name="track">
        <xsl:with-param name="trackid" select=
"key[text()='Track ID']/following-sibling::integer" />
      </xsl:call-template>
    </xsl:for-each>
  </xsl:template>

  <xsl:template name="track">
    <xsl:param name="trackid" />
      <xsl:variable name="url" 
select="//plist/dict/key[text()='Tracks']/ \
following-sibling::dict/dict/key[text()='Track ID']/ \
following-sibling::integer[text()=$trackid]/../ \
key[text()='Location']/following-sibling::string" />
<xsl:value-of select="$url" /><xsl:value-of select="$newline" />
    </xsl:template>

</xsl:stylesheet>

Piping the output of this transform to a file with the .m3u extension will result in a double-clickable file that will play in WinAmp, iTunes, or even the Mac OS X Finder. This stylesheet can easily be extended to create an extended M3U or PLS file.

You can also create arbitrary playlists on the fly simply by creating the right XPath query.

The Web

Apple provides a browser-based service that allows you to look up a particular song or artist in the iTunes Music Store. Available online at phobos.apple.com/WebObjects/MZSearch.woa/wa/itmsLinkMaker, the ITMS Link Maker allows you to search for a song, album, or artist, and creates a link to direct the iTunes music player to the song in the music store. This could be useful if, for example, you publish a list of recently played songs on your weblog, and you want to let your readers buy the songs you've recently listened to.

Apple also provides a service to create an RSS feed of iTunes songs based on criteria you select, including genre, regional music store (France, Germany, U.K., or U.S.), feed type (new releases, just added, iTunes top songs, iTunes top albums, or featured albums and exclusives), feed size (from five to 100), and whether to show explicit content. Located on the Web at phobos.apple.com/WebObjects/MZSearch.woa/wa/MRSS/rssGenerator, this service returns a URL for your criteria. For example, an RSS feed of the top ten folk songs in the U.S. iTunes music store would be available at this URL.

Parsing RSS 2.0 is left as an exercise for the reader.

Amazon and Google

Amazon.com recently announced the beta trial of their web services version 4.0. Using Mono's wsdl tool, we can generate web-service client code with the following command line:

wsdl http://aws-beta.amazon.com/AWSSchemas/AWSProductData/beta/US.wsdl

That command produces a file called AWSProductData.cs, which can be used to communicate with the Amazon.com web services.

Similarly, Google's web API is available as a WSDL, which can be downloaded with the Google Web API SDK. Once you've produced GoogleSearchService.cs, you can use it in much the same way.

For example, you can look up any artist in the Amazon.com catalog and return a list of that artist's recordings and any similar recordings. Then you can look up the artist in Google and find a number of related web sites. The following program does just that:


using System;
using System.Collections.Specialized;
using System.Text;

namespace LookupArtist
{
  class LookupArtist
  {
    private StringCollection similars = new StringCollection();
    private StringCollection discs = new StringCollection();
    private const string amazonKey = "xxxx";
    private const string googleKey = "yyyy";

    static void Main(string[] args)
    {
      string artist = args[0];
      LookupArtist search = new LookupArtist(artist);
    }

    LookupArtist(string artist)
    {
      AmazonSearch(artist);

      GoogleSearch(artist);
    }

    private void AmazonSearch(string artist) {
      ItemSearch search = new ItemSearch();
      search.SubscriptionId = amazonKey;
      search.Request = new ItemSearchRequest[1] 
        { new ItemSearchRequest() };
      search.Request[0].SearchIndex = "Music";
      search.Request[0].Artist = artist;
      search.Request[0].ResponseGroup = new string[] 
        { "Similarities", "ItemAttributes" };
      AWSProductData productData = new AWSProductData();
      ItemSearchResponse response = productData.ItemSearch(search);
      foreach (Items items in response.Items) {
        foreach (Item item in items.Item) {
          if (!discs.Contains(item.ItemAttributes.Title)) {
             discs.Add(item.ItemAttributes.Title);
          }
          foreach (SimilarProductsSimilarProduct sim in 
            item.SimilarProducts)
          {
            string s = string.Format("{0} (ASIN {1})", 
              sim.Title, sim.ASIN);
            if (!similars.Contains(s)) {
              similars.Add(s);
            }
          }
        }
      }

      Console.WriteLine("Discs by {0}:", artist);
      foreach (string disc in discs) {
        Console.WriteLine("\t{0}", disc);
      }
      Console.WriteLine("Similar discs:");

      foreach (string similar in similars) {
        Console.WriteLine("\t{0}", similar);
      }
    }

    private void GoogleSearch(string artist) {
      GoogleSearchService search = new GoogleSearchService();
      GoogleSearchResult result = 
        search.doGoogleSearch(googleKey,
          artist, 0, 10, false, string.Empty,
          false, string.Empty, string.Empty, 
          string.Empty);
        Console.WriteLine("Related web sites:");
        foreach (ResultElement element in result.resultElements) {
          Console.WriteLine("\t{0} <{1}>", 
            element.title, element.URL);
        }
      }
    }
  }
}

Be sure to replace the values of the variables amazonKey and googleKey with the appropriate developer ID for each service.

Searching for John Coltrane, for example, produces this output:


Discs by John Coltrane:
        Kind of Blue
        A Love Supreme
        Thelonious Monk with John Coltrane
        John Coltrane & Johnny Hartman
        The Ultimate Blue Train
        My Favorite Things
        Giant Steps [Deluxe Edition]
        Very Best of John Coltrane
        Love Supreme (Dlx) (Dig)
        Live at Birdland
Similar discs:
        Time Out (ASIN B000002AGN)
        Sketches of Spain [Bonus Tracks] (ASIN B000002AH7)
        The Ultimate Blue Train (ASIN B000005H7D)
        Birth of the Cool (ASIN B00005614M)
        Thelonious Monk with John Coltrane (ASIN B000000Y2F)
        Kind of Blue (ASIN B000002ADT)
        My Favorite Things (ASIN B000002I53)
        Giant Steps [Deluxe Edition] (ASIN B000003489)
        Saxophone Colossus (ASIN B000000YG5)
        Collection: 1947-1972 (ASIN B00000BKK5)
        Sarah Vaughan W/ Clifford Brown (ASIN B00004NHCC)
        Ballads (ASIN B000003N7I)
        Getz/Gilberto (ASIN B0000047CX)
        I Just Dropped by to Say Hello (ASIN B000003N83)
        A Love Supreme (ASIN B0000A118M)
        The Essential Charlie Parker (ASIN B000001E03)
        Miles Davis - Greatest Hits [Columbia 1997] (ASIN B000002ALA)
        A Love Supreme: The Story of John Coltrane's Signature Album (
		     ASIN 0670031364)
        Live at Birdland (ASIN B000003N8O)
        Crescent (ASIN B000003N8R)
        The Complete 1961 Village Vanguard Recordings (ASIN B000003NA3)
        Live At The Village Vanguard: The Master Takes (ASIN B0000065KK)
        The Complete Africa/Brass Sessions (ASIN B000003N7U)
Related web sites:
        ::: JOHNCOLTRANE.COM ::: <http://www.johncoltrane.com/>
        ::: JOHNCOLTRANE.COM :::
          <http://www.johncoltrane.com/automat/swf/main.htm>
        <b>JOHN</b> <b>COLTRANE</b>
          <http://home.att.net/~dawild/john_coltrane.htm>
        The Recordings of <b>John</b> <b>Coltrane</b>: A Discography
          <http://home.att.net/~dawild/john_coltrane_discography.htm>
        Artists: <b>John</b> <b>Coltrane</b>
          <http://www.northwestern.edu/WNUR/jazz/artists/coltrane.john/>
        <b>John</b> <b>Coltrane</b> | My Favorite Things
          <http://www.room34.com/coltrane/>
        A Tribute to <b>John</b> <b>Coltrane</b>
          <http://www.geocities.com/BourbonStreet/5066/trane.html>
        Jazzone Online's <b>John</b> <b>Coltrane</b> Page
          <http://www.geocities.com/BourbonStreet/Square/9063/index/coltrane.html>
        <b>John</b> <b>Coltrane</b> discography
          <http://webusers.siba.fi/~eonttone/trane.html>
        PBS - JAZZ A Film By Ken Burns: 
		     Selected Artist Biography - <b>John</b> <b>...</b>
          <http://www.pbs.org/jazz/biography/artist_id_coltrane_john.htm>

Summary

I hope I've given you some ideas of ways to mess with an XML file that every iTunes user has on his or her hard disk, the iTunes Music Library. Of course, there is a lot more you can do. I haven't even fully explored the capabilities of Amazon and Google, much less investigated the full scope of web services out there.


Comment on this articleShare your experience in our forums.
(* You must be a
member of XML.com to use this feature.)
Comment on this Article


Titles Only Titles Only Newest First
  • Decoding the iTunes Music Library Location field
    2009-11-05 05:56:42 garberfc [Reply]

    iTunes was complaining about some inconsistencies between itself and my external music library. So I wrote a program to cross check all the entries in the file iTunes Music Library.xml with my music library.


    The full file specification for each song is in the field:
    <key>Location</key><string>file://localhost/D:/CatAudio/Enya/Watermark/11%20Na%20Laetha%20Geal%20M'%C3%B3ige.mp3</string>


    As you can see in the <string/> portion of the pair there are some 'funny' values that need translation. The values are always preceded by a percent (%) sign followed by two hexadecimal digits. These can be considered escape sequences for characters that don't lend themselves to XML data.


    Most of the translations are pretty straight forward. Find a unicode chart like this one: http://www.ssec.wisc.edu/~tomw/java/unicode.html#x0000 An example is %20 translates to a space. The difficulty comes in with two specific codes: %C3 and %C2. These work like tuples. When either is encountered, the following three characters are ALWAYS another code. When a %C2 is encountered the following code can be directly converted. When a %C3 is encountered the hex value x40 must be added to the code, then translated to a character.


    Good Luck!

  • ermmmm...
    2008-05-30 04:24:52 lukxz [Reply]

    I only wanted to convert an itunes song to a different file type so i could put it on windows movie maker, why did you have to go and confuse me like this. If you can't be bothered explaining to me what i need to do, please may you show me a link that can help me? thanks

  • Smart Playlist Decoding
    2008-04-06 13:15:41 the_ev [Reply]

    Nice article! Can't say I understand all of it yet, but I'll get there (XML is a little new to me).


    Anyway, I was intrigued by this: ""Smart" playlists have the additional keys Smart Info and Smart Criteria, which contain base-64-encoded data that specifies the smart playlist."


    I've tried decoding the 'Smart Info' and 'Smart Criteria' keys, but I don't get easily understandable results back. The 'Smart Info' generally returns nothing, and the 'Smart Criteria' returns something like this (for one key):


    SLst(Dá
    ÉT¼@‘»á
    ÉT¼@‘»D11


    I'd really like to understand how to decipher these fields, because I'm not happy with the built-in Smart Playlist evaluations, and I'd like to program an app or script that will give me more range in making my Smart Playlists; can anyone help me with this? Thanks!

  • Where is the "checked" attribute kept?
    2006-05-06 19:49:48 Itamar [Reply]

    Hi,


    Great article!
    I was wondering if you knew where the "checked" state of a song is kept. I have looked for it and not found it. I mean that checkbox that is to the left of the song name in iTunes. I would like to set it programmatically;
    Do you have an idea?
    Thanks
    Itamar


  • Great stuff, I'm making a phpversion of it!
    2006-04-28 15:37:59 mskogly [Reply]

    http://poetikon.no/temp/phpxml/class_xslt/podcaster3.php


    I exported my podcastsection in Itunes as a separate xml and used your playlist example to generate a sort for blogroll list (except without urls), by listing Albums. As you can see on that url I'm stuck at finding a way to only list unique Albums though, I've read though http://www.w3.org/TR/xpath and their xslt section, as well as googling, but so far I've had no luck finding an XSLT-method to do this. Is it at all possible? Any tips would be greatly appreciated.


    I'm writing about it in this blogpost, feel free to drop a comment.


    http://pappmaskin.blogspot.com/2006/04/putting-you-itunes-playlist-on-your.html