Friday, July 3, 2009

Reading the Playlists from the iTunes Library XML

Once you have selected an iTunes Library XML (or if the default location is working), the code reads through the XML file to figure out which playlists are in the file.

The playlist is stored in an instance variable (line 1) that is instantiated with the filename as a parameter (line 3):

private Library _library;
...
_library = new Library(txtLibrary.Text);

In the constructor of the Library class the XML file is read:

public Library (string pfileName) {
 // no other way to set the root
 _root = XElement.Load(pfileName);
 _playlists = null;
}

Line 3 is the first line of code that uses LinqToXML ... not much too it. For a production environment, some kind of error handling would probably have to be added. The instance variable _playlists is not initialized, it will be set up at the time it is accessed.

The fist access happens when the playlists are to be displayed in the list box. This code is from the Playlist Converter Form right after instantiating the _library instance variable:

foreach (Playlist pl in _library.getPlaylists()) {
 lbPlaylists.Items.Add(pl);
}

Getting the playlists requires some XML reading:

public List<Playlist> getPlaylists ()
{   // lazy initialization
 if (_playlists == null)
 {
     _playlists = new List<Playlist>();

     //Query XML for Playlists
     XElement rootList = (from element in _root.Descendants()
                          where element.Value.Equals("Playlists")
                          select element).First().NextNode as XElement;
     IEnumerable<XElement> listIDs = (from listFields in rootList.Descendants()
                                        where listFields.Value.Equals("Playlist Persistent ID")
                                        select listFields);
     foreach (XElement list in listIDs)
     {
         _playlists.Add(new Playlist(list.Parent as XElement));
     }
 };
 return _playlists;
}

The method returns a list of playlists. If the instance variable is already initialized, it is just returned in a getter fashion. Otherwise we build the list in a few simple steps.

First, we find the root element for the playlists in the XML file with the query in lines 8 to 10. We look for a node that has a value of “Playlists”. There is only one in the file, so “.First” returns this single node. The array of playlists is the next node after that, so “.NextNode” returns this array.

Once we have that array, we can then query in it for the individual playlists. Lines 11 to 13 looks for all the “Playlist Persistent ID” nodes in this array. Then we can iterate through these elements and build Playlist objects with the dict for an individual playlist (line 16).

After each of these new playlist objects has been instantiated, they can just be added as an item to the listbox. In order for the listbox to properly display these items in a list, the ToString() member of the playlist will be called. This will be described in the next post …

Main | Next

No comments:

Post a Comment