Friday, June 26, 2009

Base functionality of the Form

Here is a screenshot of the form in designer view:

image

This form is just relatively simple C'# code (the LinQ2XML will be described in future posts). I’ll just point out a few of the important parts:

Choosing the iTunes library

This field holds the fully qualified filename for the iTunes library. There is a sensible default (line 11), but you can choose a different location with the “Choose …” button (code in lines 27ff.)

Populating the listbox of playlists (lbPlaylists)

This listbox holds the playlists in the iTunes library. It is populated at the startup of the form and whenever a different library path is chosen. We’ll have a closer look at the code that achieves this behavior in another post (lines 18ff.).

Select all / Select None of the entries in lbPlaylists

These are just shortcuts to make selecting all or unselecting of the playlists easier. (Or is it select none?!) It’s just a simple loop over all the items in the listbox (lines 64ff and 72ff).

Choosing the path for the converted playlists (noxon Library)

Another simple data field that holds the directory the converted playlists are to be written to. The behavior of the selection dialog is a little bit different than the one for the iTunes library (lines 46ff).

Convert the playlists

The code that is triggered by clicking the “Convert” button will be described in another post.

Here’s the main part of the form code:

public partial class frmConverter : Form
  {
      private Library _library;

      public frmConverter()
      {
          InitializeComponent();
          txtLibrary.Text =
                 Environment.GetFolderPath(Environment.SpecialFolder.MyMusic)
                 + "\\iTunes\\iTunes Music Library.xml";
          txtResultPath.Text = "\\\\Marvin\\musik\\Playlists";
          // for testing
          //txtResultPath.Text = "C:\\temp\\Playlists\\";
          _library = new Library(txtLibrary.Text);
          populate_lbPlaylists();          
      }

      private void populate_lbPlaylists()
      {
          lbPlaylists.Items.Clear();
          foreach (Playlist pl in _library.getPlaylists())
          {
              lbPlaylists.Items.Add(pl);
          }
      }

      private void btnChooseLibrary_Click(object sender, EventArgs e)
      {
          OpenFileDialog dlg = new OpenFileDialog();
          dlg.Filter = "iTunes Library (*.xml)|*.xml";
          dlg.InitialDirectory = Path.GetDirectoryName(txtLibrary.Text);

          if (dlg.ShowDialog() == DialogResult.OK)
          {
              txtLibrary.Text = dlg.FileName;
              _library = new Library(txtLibrary.Text);
              populate_lbPlaylists();
          }
      }

      private void btnClose_Click(object sender, EventArgs e)
      {
          this.Close();
      }

      private void btnChooseResult_Click(object sender, EventArgs e)
      {
          FolderBrowserDialog dlg = new FolderBrowserDialog();
          dlg.SelectedPath = Path.GetDirectoryName(txtResultPath.Text+"\\");
          dlg.Description = "Choose the path to write the playlists to:";
          dlg.ShowNewFolderButton = false;

          if (dlg.ShowDialog() == DialogResult.OK)
          {
              txtResultPath.Text = dlg.SelectedPath;
          }
      }

      private void btnConvert_Click(object sender, EventArgs e)
      {
   // more on this later
      }

      private void btnAll_Click(object sender, EventArgs e)
      {
             for (int i = 0; i < lbPlaylists.Items.Count; i++)
              {
                  lbPlaylists.SetSelected (i, true );
              }
      }

      private void btnNone_Click(object sender, EventArgs e)
      {
          for (int i = 0; i < lbPlaylists.Items.Count; i++)
          {
              lbPlaylists.SetSelected(i, false);
          }
      }
  }

Main | Next

Thursday, June 11, 2009

A look at the iTunes XML and playlist formats

The playlist converter basically grabs the playlists in iTunes and converts them into a different format. Before looking at the code, here is a short description of the relevant formats.

iTunes XML

iTunes stores the “meta-information” about the music, playlists etc. that you can use and set up in iTunes in an XML file called “iTunes Music Library.xml” which is usually stored in the iTunes music folder (usually My Documents\My Music\iTunes).

There is a couple of web documents that describe the format. I have used an article by Niel Bornstein called “Hacking iTunes”. Some examples here are taken from this article.

There are three main sections in the file:

  1. some meta info (such as general location infos, version etc.)
  2. tracks info (a large dictionary of track information)
  3. playlists info (a large dictionary of playlist information)
Tracks

For each track, there is number of key – value pairs. ‘Key’ can be Track ID, Name, Artist and Location, whereas value can be a number or string which denotes the key’s value, e.g.

 <key>Track ID</key><integer>839</integer>
<key>Name</key><string>Sweet Georgia Brown</string>
<key>Artist</key><string>Count Basie & His Orchestra</string>
<key>Composer</key><string>Bernie/Pinkard/Casey</string>
<key>Location</key><string>file://localhost/Users/niel/Music/iTunes/iTunes%20Music/Count%20Basie%20&%20His%20Orchestra/Prime%20Time/03%20Sweet%20Georgia%20Brown.m4p</string>
Playlists
Each playlist also has some meta information (such as name etc., lines 2 to 4) and an array with the TrackIDs of the tracks that make up the playlist (lines 7 to 14):
<dict>
<key>Name</key><string>Funky</string>
<key>Playlist ID</key><integer>6652</integer>
<key>Playlist Persistent ID</key><string>88CED99A2F698F3C</string>
<key>All Items</key><true/>
<key>Playlist Items</key>
<array>
<dict>
<key>Track ID</key><integer>837</integer>
</dict>
<dict>
<key>Track ID</key><integer>754</integer>
</dict>
</array>
</dict>
This playlist (called “Funky”) contains two tracks (with the IDs 837 and 754). Information about these tracks can be obtained from the tracks section using the IDs. As this is a “plain” XML file, it can be queried using LinQ To XML.

M3U playlist

The M3U playlist format is very simple, it is just a list of the files to be played, each title in its own line:
\\Marvin\musik\Download\Run\01 01 Mornin'.mp3
\\Marvin\musik\Download\Run\13 08 Man Of La Mancha (I, Don Quixote).mp3
\\Marvin\musik\Download\Bike\01 01 Child's Anthem.mp3
This playlist contains three titles, each denoted by the location of their MP3 files. Additional information (Artist, Title, Album etc.) can only be obtained from the meta-information stored in the MP3 files. The file is a plain text file – as I only have to write to this file, I’m just using a simple TextStream to write to. If the format was a bit more involved (say another, maybe differently formatted XML file), I could have used LinQToXML again, but it would be overkill for writing M3U files.

Main | Next

Saturday, June 6, 2009

A first look at the PlaylistConverter

The general idea behind the PlaylistConverter is described in a previous post.

Here’s a screenshot of the PlaylistConverter GUI:

image

On the top is the location of your iTunes library. The program uses a sensible default so usually there is no need to point the program to a specific location using the Choose-button to the right.

The middle part lists all the playlists in your iTunes library. It also displays some “internals” (such as the ID of the playlist) and the number of titles in the playlist. From the available lists, you can choose one or more lists to be exported. The ‘Select All’ and ‘Unselect All’ buttons make life a bit easier.

Under the list of playlists is the location that the playlists will be exported to (the so-called ‘noxon Library’ which is actually a folder on my Windows Home Server). I’ve hard-coded a default for my environment, but again you can choose a different location with the Choose-Button.

If you click ‘Convert’ the selected playlists will be converted and saved in the noxon library directory. Each playlist will be saved in an individual file. The file locations of the titles will be changed according to the paths on the Home Server.

So with this program, my wife can set up a playlists on her own computer in iTunes and convert it into a format and locations on the Windows Home Server. There, TVersity picks up the new content and makes it available to the noxon.

End result: You set up a playlist on your own PC and you can play this list on the noxon. Pretty cool!

Here's a list of the posts that describe the PlaylistConverter:

If the current functionality is not sufficient, here are some ideas for extensions. Also, when you're interested in the full source code or an installer, drop me an email.

Friday, June 5, 2009

Introducing the iTunes Playlist Converter (with C# and LinQ)

Here’s the scenario that needed a solution:

  • My wife and I both have our individual PCs with our music collections (not too much overlap between us ;-)). Originally it was mostly ripped CDs but since iTunes und Amazon started selling MP3s without any DRM, we’ve mostly switched to “digital downloads”.
  • We also have a Noxon “internet radio” in our living room so we can listen to Internet streams through wireless LAN.
  • Occasionally we also want to play music from our individual collections (e.g. background music for parties, especially “seasonal” music at Christmas) on our living room stereo.

We could have copied the MP3s to a thumb drive and hooked that up to the Noxon, but that sounded a bit manual. (C’mon - you buy your music digitally from Apple or Amazon, it gets delivered to your PC from America or wherever, but in order to play it on your stereo you have to “sneakernet” it to the living room!) So I was looking for a better solution …

After looking around a bit, I tried TVersity. It is a “streaming server” using the UPnP protocol. TVersity publishes a list of available media to the Noxon, and can stream titles or playlists that are then played on the Noxon using my local wireless LAN.

TVersity even works on my Windows Home Server. So just copy all our music on a regular basis to the Home Server where TVersity can find it, and your almost done. This works great for individual titles and full albums, but playlists don’t.

First, we both use iTunes to manage our music, and iTunes has its own way of storing the playlists (using one larfge file an XML format, and it’s a format that is not supported by the Noxon which uses an individual M3U file for each playlist). Second, all the references in the playlist are to files local to each PC and that is different from where the files are stored on the home server.

A good scenario to try out some C# programming! Also, as iTunes uses an XML file to store all its information, I could play around with LinQ to query the contents.

The book I used to get up to speed on LinQ was this:

I found this to be quite well written, but I needed the work of “doing it myself” before I was able to figure out which parts I had not quite understood. Pretty normal for anything new!

Next: A first look at the PlaylistConverter