I’m working on a little sample application for music management in Silverlight using WCF RIA Services and some other new Silverlight 4 features.  One thing that I wanted to add to the application was the ability to drag an audio file and either lookup the data and/or add a new album/artist/song to the library automatically.

Audio formats have a ‘tag’ format known as ID3.  It’s a format used for audio file metadata that is used in Windows Media Player, iTunes, and various hardware devices as well.  Over the years there has been an evolution of this format, with the older ID3v1 format basically taking up a header space with fixed character spaces for various things like Album, Artist, Title, Year, Track.  Over time though the ID3v2 format has been adapted more as it is more flexible for things like album art, and longer titles, etc.  There are various implementations of ID3 libraries for .NET that developers can choose from.  All of these implementations don’t take into account Silverlight unfortunately.

Silverlight can only reference Silverlight-compatible libraries.  Most of these libraries were targeted for the full .NET Framework and thus I can’t binary reference them.  Luckily most of them (except one) are Open Source so I could tinker.  I took the step of simply copying the files to a Silverlight project and recompiling.  This did not work 100% in a single task.  Most of the libraries had some form of Serialization attributes/constructors and almost all used some form of ASCII encoding for various string manipulation of byte arrays.

I settled on TagLib# as the library that was the easiest to modify for me.  I had to make the same changes I mentioned above to this library as well.  I created a new Silverlight 4 class library and compiled it as such.  One thing that TagLib# didn’t have was a stream input implementation.  Most of the libraries, in fact, assumed a local file path.  Luckily the library was written using a generic ‘File’ interface, so I just had to create my own StreamFileAbstraction.  I chose to do this within my project rather than the base library.  It was easy since the LocalFileAbstraction actually perfomed an Open on the file as it’s first task and set some public variables.  My abstraction basically just hands the stream already and ready to go.

Now, using the Silverlight 4 drop target feature, I created just a simple test harness to test my theory.  My XAML basically is this (pretty rudimentary just to test my theory):

   1: <Grid x:Name="LayoutRoot" Background="White">
   2:         <StackPanel>
   3:             <Border x:Name="DropZone" Width="700" Height="300" Background="Silver" CornerRadius="8" AllowDrop="True" Drop="DropZone_Drop">
   4:                 <TextBlock TextWrapping="Wrap" Text="drop here" FontSize="64" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Gray"/>
   5:             </Border>
   6:             <Grid Height="255" Width="700">
   7:                 <Grid.ColumnDefinitions>
   8:                     <ColumnDefinition Width="111"/>
   9:                     <ColumnDefinition Width="*"/>
  10:                 </Grid.ColumnDefinitions>
  11:                 <Grid.RowDefinitions>
  12:                     <RowDefinition Height="Auto"/>
  13:                     <RowDefinition Height="Auto"/>
  14:                     <RowDefinition Height="Auto"/>
  15:                     <RowDefinition Height="Auto" />
  16:                     <RowDefinition Height="50*" />
  17:                 </Grid.RowDefinitions>
  18:                 <dataInput:Label Content="Artist" HorizontalAlignment="Right" VerticalAlignment="Top" FontWeight="Bold" Margin="4" />
  19:                 <dataInput:Label Content="Album" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Top" FontWeight="Bold" Margin="4" />
  20:                 <dataInput:Label Content="Title" Grid.Row="2" HorizontalAlignment="Right" VerticalAlignment="Top" FontWeight="Bold" Margin="4" />
  21:                 <dataInput:Label Grid.Column="1" HorizontalAlignment="Left" Name="Artist" Margin="4" />
  22:                 <dataInput:Label Grid.Column="1" Grid.Row="1" HorizontalAlignment="Left" Name="Album" Margin="4" />
  23:                 <dataInput:Label Grid.Column="1" Grid.Row="2" HorizontalAlignment="Left" VerticalAlignment="Top" Name="Title" Margin="4" />
  24:                 <Image Grid.Column="1" Grid.Row="4" Height="118" HorizontalAlignment="Left" Margin="4,2,0,0" Name="AlbumArt" Stretch="Fill" VerticalAlignment="Top" Width="118" />
  25:             </Grid>
  26:         </StackPanel>
  27:     </Grid>

Notice on the Border the AllowDrop=”True” attribute.  This tells Silverlight that the element can be used as a drop target (for a file from the file system).  The rendered UI looks like this:

Sample MP3 test UI

You may also notice the Drop attribute on the Border element that maps to the event handler DropZone_Drop.  This event handler basically gives us an event argument that represents the dropped objects on the surface (yes you can drop more than one).  The initial stub of this function looks like this:

   1: private void DropZone_Drop(object sender, DragEventArgs e)
   2: {
   3:     IDataObject drop = e.Data as IDataObject;
   4:  
   5:     object data = drop.GetData(DataFormats.FileDrop);
   6:  
   7:     FileInfo[] files = data as FileInfo[];
   8:  
   9:     FileInfo file = files[0];
  10: }

I’m being a little verbose in the code to show each of the steps.  As you can see you get a FileInfo array and can pull items out of that.  For my sample I’m just assuming one item was dropped.  In the next steps I just need to get the Stream from the file and use my library.  Here is the full function (with a quick check to make sure it is a supported audio file):

   1: private void DropZone_Drop(object sender, DragEventArgs e)
   2: {
   3:     IDataObject drop = e.Data as IDataObject;
   4:  
   5:     object data = drop.GetData(DataFormats.FileDrop);
   6:  
   7:     FileInfo[] files = data as FileInfo[];
   8:  
   9:     FileInfo file = files[0];
  10:  
  11:     if (file.Extension.ToLower() != ".mp3" && file.Extension.ToLower() != ".wma")
  12:     {
  13:         MessageBox.Show("Must be an MP3 file");
  14:     }
  15:     else
  16:     {
  17:         Stream fileStream = file.OpenRead();
  18:  
  19:         TagLib.File.IFileAbstraction fileAbstraction = new StreamFileAbstraction(fileStream, file.Name);
  20:  
  21:         TagLib.File tagFile = TagLib.File.Create(fileAbstraction);
  22:  
  23:         if (tagFile.Tag.TagTypes.HasFlag(TagLib.TagTypes.Id3v2))
  24:         {
  25:             Artist.Content = tagFile.Tag.FirstAlbumArtist;
  26:             Album.Content = string.IsNullOrEmpty(tagFile.Tag.Album) ? "NO ALBUM NAME" : tagFile.Tag.Album;
  27:             Title.Content = tagFile.Tag.Title;
  28:             if (tagFile.Tag.Pictures.Length > 0)
  29:             {
  30:                 IPicture pic = tagFile.Tag.Pictures[0];
  31:                 MemoryStream img = new MemoryStream(pic.Data.Data);
  32:                 BitmapImage bmp = new BitmapImage();
  33:                 bmp.SetSource(img);
  34:  
  35:                 AlbumArt.Source = bmp;
  36:             }
  37:         }
  38:         else
  39:         {
  40:             MessageBox.Show("no id3v2 tag");
  41:         }
  42:     }

Once all the pieces are together you drag an audio file on the drop surface and the items will populate.  Here’s a quick video showing how it all works together.

Get Microsoft Silverlight

So this is just a start – and I’ve got only the tag reading working…didn’t bother looking at the other parts of the library so I know it isn’t fully ported for Silverlight.

What do you think?  Found a better implementation of ID3 tag reading?



As noted in a previous update post on my Foxit PDF Previewer for Outlook and Vista/Windows 7, there is an issue in the Office 2010 64-bit Beta (specifically Outlook) for executing 32-bit preview handlers on 64-bit Outlook.  I’ve got an update for those temporarily.

First, I can confirm that the issue is fixed in the later builds of Outlook 2010, so this fix is indeed only temporary.

Thanks to some assistance that Leo Davidson provided, I was able to provide a work around for my previewer that I’ve been able to confirm “works for me” on my installation of Outlook 64-bit on Windows 7 64-bit edition.

WARNING: This temporary fix involves messing with your registry.  You should do this with caution.  While I’ve done it successfully and tested fine, don’t hold me responsible if you computer catches on fire or neighbor pet animals die by doing this.  You should backup your registry before applying this to be safe.  Again, that said, it’s minor, only updates my application area settings and shouldn’t interfere with your settings.

The fix involves massaging some registry settings.  I’ve provided the registry settings in a file you can download here: FoxitPreviewerTempFix.zip.  There are two (2) registry files here.  Even though they are labeled 32-bit and 64-bit, they both need to be merged for this fix to work.  You should be able to double-click the .reg file and it will merge it auotomatically.  Additionally you can start regedit.exe and use the Import option (this is what I do).

Once complete, and assuming you have my previewer installed, then PDF preview attachment with my handler for Outlook 64-bit should be fixed for you.  Again, the requirement first here is that you have my Foxit PDF Previewer installed FIRST.

Please leave comments if this solved your issue.  This is ONLY for Outlook 2010 64-bit.  This is not necessary if you are running Outlook 2010 (32-bit), even if you are on Windows 64-bit.  That’s a lot of ‘bit’ talk I know.

Hope this helps! (and thanks Leo!)

Remember the final moments of the Scott Guthrie keynote presentation at PDC09?  Where Brian Goldfarb came on stage and demonstrated a completed application using a lot of the features of Silverlight 4?  Yeah, that Facebook application.  Well, it’s here now!

Microsoft Silverlight 4 Beta Client for Facebook

Silverlight Client for Facebook - Home view

The Microsoft Silverlight 4 Beta Client for Facebook has been released as a developer preview sample.  In order to use it you must have Silverlight 4 developer builds installed.

NOTE: When you run this application you’ll be installing the developer builds of Silverlight.  When Silverlight 4 releases, unless you are a developer, you’ll likely want to uninstall this plugin and install the released software.  This sample application is being provided as a developer preview to showcase and inspire.

The application is installed as a trusted application and does all the things you’d expect for Facebook.

Status updates:

Silverlight Client for Facebook - Status updates

Drag/drop pictures from your computer to a photo album:

Silverlight Client for Facebook - Add photo

A photo feed view:

Silverlight Client for Facebook - photo feed

Notifications for messages to you:

Silverlight Client for Facebook - notification window

Add a photo to a post using your web camera on your computer:

Silverlight Client for Facebook - Webcamera input

And yes, anyone uploading video to Facebook can be played back in the app as well:

Silverlight Client for Facebook - flash video playback in Silverlight

A lot of cool ways to explore your Facebook information (sorry, no mafia war games…for me that’s a good thing).  You can also see some Outlook integration if you right-click on events that you may have to send an email and such (I don’t have any events in my Facbook account to snapshot).

So what’s NOT in there?

Good question.  At PDC09 you may have seen a few things that I haven’t mentioned yet above.  The chromeless (borderless application) aspect of the application is not in this preview.  This is because the beta of Silverlight doesn’t include that feature right now.  Additionally the plug-in the camera and have it automatically import the pictures is not in this preview as well.  That was implemented using some COM integration and the team just didn’t clean that code up for this preview for the public.

What about source code?

At this time no source code is being provided…and probably won’t be.  I’m not the decision maker on ultimately if it will or not, just my assumption.  The Facebook client is meant to be a working demonstration/inspiration of what one could do with existing services and providing different views into an existing application framework.

How can I install this and will it work on my Mac?

You can play around with the app by visiting the Microsoft Silverlight 4 Beta Client for Facebook app on the Silverlight samples site (which also includes the other sample applications from PDC09).  As a reminder, this is a developer preview build and intended for developers.  You will need to have Silverlight 4 installed on your machine (which is a beta plugin).  The link to the app will direct you where you can get the appropriate download.

Yes, it will work on your Mac (as long as you have an Intel processor version).  When you install the app you’ll see the Apple preferred install guidelines to drag the application to your Applications folder and can navigate to it there or use Spotlight search to find it.

This is a fun little application to navigate your Facebook account.  The team had a good time building it and is excited to share it with others.  Have fun!

Below is a list to links of my Windows 7 themes that are based on the Smashing Magazine monthly desktop wallpaper posts.  Simply click on your desired theme pack (you must have Windows 7) and it will run.  These themes all use the default Windows sound themes (minus the start navigation) and are set to rotate every 30 minutes.  You can adjust those settings to your liking after installed.  They also use the 1920x1200 resolution pictures from the post as the maximum/best provided for each author.

I do my best to get them out as soon as Smashing Magazine publishes their final selections.  Hope you enjoy them…I do!

As we’ve all been guilty, when you see demonstrations of technologies most of the time the data samples show single table solutions.  When was the last time you’ve developed a single-table system? :-)  Thought so.

In RIA Services demonstrations, most of them have been single-table samples as well.  So how do you go about retrieving relational data (master/details type) with RIA Services?  Here’s an option.  I’m using VS2010, Silverlight 4 and the WCF RIA Services preview using the below sample.  I’m also using the Chinook sample database which has become one of my favorite simpler relational data samples to use.

Creating your project and associated RIA Services

This is easy, create a new Silverlight project and make sure the ‘Enable .NET RIA Services’ link is checked (yes, we know it doesn’t say WCF in that dialog).  My Silverlight application will be a simple button to retrieve artists then show their associated albums.  Here’s my XAML to start:

   1: <Grid x:Name="LayoutRoot" Background="White">
   2:     <StackPanel Width="400">
   3:         <Button Content="Get Artist Information" x:Name="GetArtistButton" Click="GetArtistButton_Click" />
   4:         <StackPanel Orientation="Horizontal">
   5:             <StackPanel x:Name="ArtistsContext">
   6:                 <StackPanel Orientation="Horizontal">
   7:                     <TextBlock Text="Artists: " />
   8:                     <TextBlock Text="{Binding ElementName=ListOfArtists, Path=Items.Count}" />
   9:                 </StackPanel>
  10:                 <ListBox x:Name="ListOfArtists" Width="200" Height="300" DisplayMemberPath="Name" ItemsSource="{Binding}"/>
  11:             </StackPanel>
  12:             <StackPanel x:Name="AlbumsContext">
  13:                 <StackPanel Orientation="Horizontal">
  14:                     <TextBlock Text="Albums: " />
  15:                     <TextBlock Text="{Binding ElementName=ListOfAlbums, Path=Items.Count}" />
  16:                 </StackPanel>
  17:                 <ListBox x:Name="ListOfAlbums" DisplayMemberPath="Title" ItemsSource="{Binding}" Width="200" Height="300"/>
  18:             </StackPanel>
  19:         </StackPanel>
  20:     </StackPanel>
  21: </Grid>

Now on the server side I need to create the associated models and domain services to be consumed.  I’m creating my model using Entity Framework and it looks like this:

Chinook Entity Model

Now I need to create my Domain Service class for that model (remember to build the solution after you create your model so it will show up in the tools).  When we create the Domain Service class be sure to enable the checkbox to generate associated classes for metadata.  Once we finish we have some stub services created for us. 

Using the Domain Service functions

We have GetArtists and GetAlbums functions we can work with.  As an example we can wire up the button click to retrieve a list of artists using the default functions we got:

   1: ChinookContext ctx = new ChinookContext();
   2:  
   3: private void GetArtistButton_Click(object sender, RoutedEventArgs e)
   4: {
   5:     ArtistsContext.DataContext = ctx.Artists;
   6:     ctx.Load(ctx.GetArtistsQuery());
   7: }

But what about when a user clicks on an Artist, we want to show the albums for that artist and not the others.  We need to modify our Domain Service to add a function:

   1: public IQueryable<Album> GetAlbumsForArtist(int ArtistId)
   2: {
   3:     return this.ObjectContext.Albums.Where(a => a.ArtistId == ArtistId);
   4: }

Now we can use that function when a user clicks on an associated artist to populate the album information:

   1: private void ListOfArtists_SelectionChanged(object sender, SelectionChangedEventArgs e)
   2: {
   3:     ListBox theList = sender as ListBox;
   4:     Artist a = theList.SelectedItem as Artist;
   5:     ctx.Albums.Clear();
   6:     AlbumsContext.DataContext = ctx.Albums;
   7:     ctx.Load(ctx.GetAlbumsForArtistQuery(a.ArtistId));
   8: }

Cool.

However, the second event handling for our master-details section for this particular data set seems unnecessary.  After all, why not just include the children data with our initial request if we *know* that we’re doing an explicit master-details view (and our set is not that large relatively speaking).

Modify the metadata classes

Remember the generated metadata classes?  Go back to it now.  You’ll see a definition of the ArtistMetadata that includes this:

   1: public EntityCollection<Album> Albums;

Notice it has an Albums collection property.  Great, so we could just modify our XAML binding to use some element binding and get the Albums property of the SelectedItem right?  Well, not yet.  If we do that, we’ll have no data.  Why is that?  Because we haven’t told RIA Services to perform the necessary additional query to get the data.  Simple add [Include] at the top of the Albums collection:

   1: [Include]
   2: public EntityCollection<Album> Albums;

And that’s what we need.  Now we can add a function to our Domain Service class to get the additional data:

   1: public IQueryable<Artist> GetArtistsWithAlbums()
   2: {
   3:     return this.ObjectContext.Artists.Include("Albums");
   4: }

Now we just need to do some clean up.  We need to change our button click code to get the GetArtistsWithAlbums query now instead of the other one first.

Remove unnecessary code and use binding to help us

Now we can remove the SelectionChanged event handler for our Artists ListBox as well as add some binding commands to our XAML like this:

   1: <Grid x:Name="LayoutRoot" Background="White">
   2:     <StackPanel Width="400">
   3:         <Button Content="Get Artist Information" x:Name="GetArtistButton" Click="GetArtistButton_Click" />
   4:         <StackPanel Orientation="Horizontal">
   5:             <StackPanel x:Name="ArtistsContext">
   6:                 <StackPanel Orientation="Horizontal">
   7:                     <TextBlock Text="Artists: " />
   8:                     <TextBlock Text="{Binding ElementName=ListOfArtists, Path=Items.Count}" />
   9:                 </StackPanel>
  10:                 <ListBox x:Name="ListOfArtists" Width="200" Height="300" DisplayMemberPath="Name" ItemsSource="{Binding}"/>
  11:             </StackPanel>
  12:             <StackPanel x:Name="AlbumsContext" DataContext="{Binding ElementName=ListOfArtists, Path=SelectedItem}" >
  13:                 <StackPanel Orientation="Horizontal">
  14:                     <TextBlock Text="Albums: " />
  15:                     <TextBlock Text="{Binding ElementName=ListOfAlbums, Path=Items.Count}" />
  16:                 </StackPanel>
  17:                 <ListBox x:Name="ListOfAlbums" DisplayMemberPath="Title" ItemsSource="{Binding Albums}" Width="200" Height="300"/>
  18:             </StackPanel>
  19:         </StackPanel>
  20:     </StackPanel>
  21: </Grid>

Notice how the DataContext of my Albums ListBox is now set using element binding to the SelectedItem of the Artists ListBox.  Then the ItemsSource of the ListBox for Albums has a {Binding Albums} command.  This is because our Artists query now includes the associated Album data and we can just reference the property.

Use with caution

While this example shows how easy it can be to have included results in your Domain Service query result, be mindful of when you are using.  For instance if you have a customer database of 1000 customers and you want all orders to be retrieved…it might not be wise to use this particular type of method. 

This presents merely another choice for areas where you may want/need it (i.e., country/state/city) for your application.

You can download the sample solution for the above code snippets here: SilverlightApplication41.zip.  Reminder that you will need to have the Chinook database installed already – it is NOT included with this sample download.

Hope this helps!