Silverlight 1.1 Audio Player Deconstructed

In my last post I announced the ReMIX07 Boston Soundtrack application and provided the iframe for embedding that application in your own web page. This post provides more detail on the architecture of the application and a pointer to the source code so that you can download it if you are interested.

The ReMIX07 Soundtrack application provides a reference on how to do the following:

  1. Hooking event handlers to XAML objects
  2. Animating XAML
  3. Calling asynchronous web services, configuring a callback and implementing a callback
  4. Looking up XAML objects by name
  5. Setting opacity values for transparent effects on XAML vector graphics
  6. Progressive download and control of MP3 audio using the <MediaElement> including playing, pausing and stopping

The architecture of the application is depicted below. The application is referenced from an <iframe> element in a web page. The Silverlight application is served up from its web host. HTML, JavaScript, XAML and the .Net Assembly are downloaded to the browser. The HTML and JavaScript are interpreted by the Browser. The XAML and .Net Assembly are executed by the Silverlight plug-in.

ReMIXSoundtrackPlayerArchitecture

The first function that the Silverlight Plug-In calls once it renders the XAML is the Page_Loaded() method in the code behind class. The first step in the Page_Loaded() method is to hookup all the the event handlers. Then an asynchronous web service call is made to the host environment from which the Silverlight application was served. For details on how to develop Silverlight 1.1 applications that invoke web services refer to my post on that topic.

//Button Event Handlers
PlayAllTracksButton.MouseEnter += new MouseEventHandler(PlayAllTracksButton_MouseEnter);
PlayAllTracksButton.MouseLeave += new EventHandler(PlayAllTracksButton_MouseLeave);
PlayAllTracksButton.MouseLeftButtonDown += new MouseEventHandler(PlayAllTracksButton_MouseLeftButtonDown);
DownloadAlbumButton.MouseEnter += new MouseEventHandler(DownloadAlbumButton_MouseEnter);
DownloadAlbumButton.MouseLeave += new EventHandler(DownloadAlbumButton_MouseLeave);
DownloadAlbumButton.MouseLeftButtonDown += new MouseEventHandler(DownloadAlbumButton_MouseLeftButtonDown);

// Play, Pause Stop event handlers for each track
T1_play.MouseLeftButtonDown += new MouseEventHandler(T1_play_MouseLeftButtonDown);
T1_pause.MouseLeftButtonDown += new MouseEventHandler(T1_pause_MouseLeftButtonDown);
T1_stop.MouseLeftButtonDown += new MouseEventHandler(T1_stop_MouseLeftButtonDown);

...

// invoke web service to load track into
ws = new RMClient.RMTrackService_Live.TrackService();
ws.BeginGetTracks(new AsyncCallback(HandleGetTracks), null);

The Web Service loads the track information from the database and formats it as a return message. The Web Service returns the track info to the Silverlight Client. The set of <TextBlock> elements that list track number, track name and duration are looked up by calling the FindName() method on the TrackCanvas object. The track info is displayed by setting the .Text property on these <TextBlock> elements.

private void HandleGetTracks(IAsyncResult iar)
{
    tracks = ws.EndGetTracks(iar);

....

    // enumerate tracks, display track info and activate play, pause and stop buttons
    for (i = 0; i < tracks.Length; i++)
    {
        TN = "T" + (i + 1).ToString();
        number = (TextBlock) TrackCanvas.FindName(TN + "_number");
        title = (TextBlock) TrackCanvas.FindName(TN + "_title");
        duration = (TextBlock) TrackCanvas.FindName(TN + "_duration");

        play = (Canvas) TrackCanvas.FindName(TN + "_play");
        pause = (Canvas) TrackCanvas.FindName(TN + "_pause");
        stop = (Canvas) TrackCanvas.FindName(TN + "_stop");

        number.Visibility = Visibility.Visible;
        title.Visibility = Visibility.Visible;
        duration.Visibility = Visibility.Visible;
        play.Visibility = Visibility.Visible;
        pause.Visibility = Visibility.Visible;
        stop.Visibility = Visibility.Visible;

        // fade the pause and stop buttons
        pause.Opacity = 0.35;
        stop.Opacity = 0.35;

        number.Text = tracks[i].Number;
        title.Text = tracks[i].Title + " - " + tracks[i].Composer;
        duration.Text = tracks[i].Duration;
    }

}

The play, pause and stop buttons are drawn using vector graphics and encapsulated in their own <Canvas>. When the user interacts with the Canvas that wraps a play, pause and stop buttons, an event handler is called which executes the Media Playback State Machine logic. That logics determines the current play state, sets the opacity on the media control buttons and calls the appropriate method on the <MediaElement> for the track of interest to either play, pause or stop playback. There is also logic for controlling playback of all the tracks, i.e. album mode for you readers who came to age in the 60's and 70's and remember album rock, b-sides and what it really meant to scratch a record.

Finally the download album button click handler uses the HTML DOM interface from code behind to invoke a file download operation. The file reference is a zip of all the MP3's that make up the collection.

HtmlPage.Navigate("https://www.bobfamiliar.com/ReMIX07Soundtrack/Music/ReMIX07BostonSoundtrack.zip");

If you are interested in hearing more of my music, please visit BobFamiliar.com. The player depicted here is based on the code for that site. The primary difference is there is logic in the BobFamiliar.com application to handle multiple albums.

Source code for this Silverlight Client and the Web Host application can be downloaded from my public SkyDrive location. The file is called RMSolution.zip:

Requirements for working with this solution are:

  • Silverlight 1.1 Alpha
  • Silverlight 1.1 Alpha SDK
  • Visual Studio 2008 Beta 2
  • Silverlight Tools for Visual Studio 2008 Beta 2
  • Expression Blend 2 September Preview

I am using SkyDrive to host my downloads. You can get you own SkyDrive with 500meg of storage in the cloud simply by using your Live ID to sign up for the beta.

Enjoy - Bob

Technorati Tags: Silverlight, ReMIX07Boston, ArchitecturePOV, .NET, Visual Studio 2008, Expression Blend