Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WPF

Use LINQ to Create Music Playlists – Revisited

5.00/5 (3 votes)
27 Apr 2009CPOL4 min read 24.2K   423  
A re-write of a previous article. Still using LINQ, but incorporating much more in this iteration 2 version.
PlaylistCreator

Introduction 

Being a bit old-fashioned, I still have my .mp3 music collection organized on my file system by genre and artist. I know, I know, download iTunes already, right?!  Well I could but then I wouldn't have had as much fun writing my own code to automatically build play lists for me. 

Once the Playlist Creator is finished building the .m3u files, you can double-click launch them through Windows Media Player or whatever media player/file extension you use.

Background 

After writing my original article about how to easily create music play lists using some simple recursion and LINQ, I reviewed my work and set out to make it better. One of the things I really wanted to "fix" in this version of the code was the ability to create a play list at each branch level of my folder tree. You see, I have my music collection organized by genre, then by artist, then by album. So I wanted the ability to launch a play list for, say the "Rock" folder which holds all my rock music, and so on and so forth anywhere in the tree.

The important topic of this code is to realize that creating play lists in this fashion would require multiple trips through the file system--with the end limbs getting hit time after time until they themselves get processed. Windows does a marvellous job at caching disc activity, but I'd rather attempt to write something efficient without having to lean on another efficiency process.

Using the Code  

Once again, the main work accomplished by this code is:

  1. Traverse the file system collecting information about files and folders
  2. Dump this information into an in-memory typed-DataSet 
  3. Iterate through the DataSet memory creating the play list

The DataSet looks like this:

PlaylistCreator_ds.jpg

A couple of simple DataTables to house the collected disk information. I still find typed DataSets handy for quick storage data tasks like this. They're easy to setup and seamless to code against.

Going for a bit more structure in my code, I have a separate assembly that provides all the work of finding the music files as well as building the playlists. All of the work tasks are done in the PlaylistCreatorFP project and this project has a main class called PCEngine that contains the main methods. 

One of the interesting tid-bits I discovered while coding this re-write was the fact that the System.IO.Directory class has a static method for finding all the directories in a given path.  Not ultra-new information, but I didn't realize that there is another parameter you can pass that will do the recursion for you:

C#
string[] dirs = Directory.GetDirectories
	(inPath, PCConstants.ALLFILES_SEARCH_PATTERN, SearchOption.AllDirectories);		 

Hooray!  No more memory exhaustive manual recursion for my disk traversals! 

The rest of the code is pretty readable [I hope ;o)] so I won't bore you all with the details here. The main methods in the PCEngine class are SearchDisk(...) and CreatePlayLists(...). The rest are supporting methods to these as well as an event created to send update messages back to the main process thread.

The UI is another story. Talk about going overboard in a CodeProject article! The UI is a small WPF interface to allow the user to enter a few choices about where to start looking for music files, how to name the generated play list files, etc. Simple stuff just to make it more of a workable program. The work is preformed by a System.ComponentModel.BackgroundWorker object to keep the UI running smoothly.  Also there's a base class for the main window that uses Isolated Storage to store the window position and size upon close.

Points of Interest 

While writing this, I learned:

  • The "built-in" recursion of the System.IO.Directory.GetDirectories(...) static method
  • Creating Relations and using the DataRelation class and its ChildRelations(...) method along with the .GetChildRows(...) row method to flatten the tree hierarchy
  • How to create delegate message events to easily pass messages back to the calling thread
  • How to build a base class to extend the Window class in WPF/XAML

History 

  • 27th April, 2009: Initial post

I'm probably going to leave this code for now. There's so many other interesting projects to tackle!  But if you find bugs or have comments, please drop me a comment!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)