Windows Live Photo Album Screen Saver

Now that I am using my Windows Live Spaces extensively for blogging and posting pictures I started to look around software that would allow me to use as a screen saver the pictures in my Photo Albums.  I use a couple of different computers and I love to have personal pictures as my screen saver, but it was such a hassle to have to copy new ones from time to time over to each machine.  At one point there was an MSN Screen Saver that purported to have this capability, but I couldn’t get it to work with my Windows Live Spaces account.

This was a great opportunity to play with VS2008 and LINQ.  I have had the Express Beta 2 version on my machine for a while, but done little with it up to this point.  I took the Screen Saver starter kit from the VS2005 Edition and upgraded the project to 2008 (by opening it in 2008).  That worked without a problem and so it was on to customizing the project to pull the files from my Windows Live Spaces albums and hooking that into the Screen Saver code.

I have uploaded the source code zipped to my SkyDrive.  There are many changes to be made, but the code is working.  I don’t have the options dialog working yet to configure through the GUI the Live Spaces Album feed to use so you’ll have to change the hard-code and recompile.  Before too long I will update the code to include that as it isn’t hard to do.  When you compile it copies the exe output and a helper dll to the system32 directory and renames the exe file to an scr file which is what Windows wants to show you the screen saver in the Screen Saver tab within the Display options.  REMEMBER YOU MUST HAVE .NET 3.5 Beta 2 INSTALLED FOR THIS TO WORK!

The RSS feed you provide can be for all your albums or from a specific album the code automatically detects it and will parse it accordingly.  The WindowsLiveSpacesPhotos.dll holds the parsing code which isn’t very complicated really.  I use LINQ in it to examine the XML and find what I need.  I love LINQ.  It changes the whole way I look at solving problems.  If I need to query data (however that data is stored) I can now express it in common terms rather than having to primitively code my queries in a sequence of loops, ifs, and temporary variables.

   1: public List<Uri> ProcessFeed(string feedURL)
   2:         {
   3:             SyndicationFeed feed = SyndicationFeed.Load(new Uri(feedURL));
   4:             var Result = (from extension in feed.ElementExtensions
   5:                              where ((XmlElement)extension.Object).Name == "live:type" && (((XmlElement)extension.Object).InnerText == "photos" || ((XmlElement)extension.Object).InnerText == "photoalbum")
   6:                          select ((XmlElement)extension.Object).InnerText);
   9:             if (Result == null) throw new ArgumentException("The feed URL provided is not a feed of all photo albums or a feed for a specific photo album and thus it is not a valid feed");
  10:             var PhotoFeedType = Result.SingleOrDefault();
  12:             if (PhotoFeedType == "photos") return EnumeratePhotoAlbums(feed);
  13:             if (PhotoFeedType == "photoalbum") return EnumeratePhotos(feed);
  14:             return null;
  16:         }

Windows Live Spaces extends RSS feeds with extended properties if you will that identify the feed if it is a photo album or if it is photos which means that it is a list of photo albums (where as photoalbum means the feed consists of a list of photos that comprise the single album).

I then use LINQ to inspect the feed to extract the items that I need.  The code snippet below I am especially proud of as it is my most advanced LINQ query to date where I am nesting queries and from one of them querying over the return from a method call.  The thing I like is the way it goes into each photo album RSS feed extracts out the links to the actual images and then returns them flattened out with all image links from all photo albums in one list.  I would try to explain it, but it is much more effective to play with this sequence of code and work with the debugger to inspect the different ways that data can get returned (nested differently).  It took some playing with it along with a little Internet searching to figure out how to get it flattened out correctly.

   1: private List<Uri> EnumeratePhotoAlbums(SyndicationFeed albumFeed)
   2:         {
   3:             var Results = (from item in albumFeed.Items
   4:                 from extension in item.ElementExtensions
   5:                     where (((XmlElement)extension.Object).LocalName == "itemRSS")
   6:                     from photolink in EnumeratePhotos(SyndicationFeed.Load(new Uri(((XmlElement)item.ElementExtensions[3].Object).InnerText)))
   7:                     select photolink).ToList();
   9:             foreach (Uri uri in Results)
  10:             {
  11:                 Console.WriteLine(uri.AbsoluteUri);
  12:             }
  14:             return Results;
  16:         }

I won’t bother showing the Screen Saver code as I didn’t change too much there.  I do spin off a new thread to check the feeds for updates and then I store them in a temp folder and when I am done downloading the images (I save them local so that the screen saver can work in the rare instance that the computer might not actually be connected to the Internet).  I then signal the UI thread and inform it of the new folder and it then switches the screen saver from using the old image folder to using the new and voila! we have our screen saver.

Once I get a little more work done on this I plan on posting it to CodePlex.  I want to clean up the code by adding in an object model to express more appropriately the domain model that exists as well as making the options dialog work like it is supposed to.  I would love to have the same image layouts and transitions that the built-in Vista Screen Saver has, but that for now is beyond me, but who knows maybe getting the code to Codeplex will help me find someone who has the know-how to do that!

This entry was posted in Technology. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s