Post filed in Silverlight

Silverlight Video Player updated to display external bookmarks

Last week someone requested a new feature to the Silverlight 2 Video player on CodePlex that would allow users to create an external list of “bookmarks”, that would link to a specific marker or moment in playback.  The idea would be to have a series of links outside of Silverlight, that once clicked,playback would jump to that moment in the video.

When I originally created marker support I had given this some thought and was just waiting for the opportunity to add this feature.  I am excited someone really wants it.  Back in July I created a post called Communicating between two Silverlight objects on a single page. In this post I demonstrate how one can use a [ScriptableMember] to expose a method to JavaScript. To add this feature to the Video Player I can use this technique.

The first step was to create a method in my mediaControls control, which would allow a time (TimeSpan) to be passed during playback.  This call will jump the slider to that position in time and begin or continue playback.

sl2video_externalLink2
sl2video_externalLinkOnce we have a method in mediaControl we can expose a scriptable method in Page.xaml. This method can be called from any page hosting out Silverlight XAP.

To demonstrate how to use this method I created a sample html page that presents a list of bookmarks that target the video player.  Each link calls a JavaScript method, that in turn calls my [ScritableMember]

sl2video_externalLink4
sl2video_externalLink3

Confined collisions with a dose of gravity

Over the past few months I have created a handful of Silverlight 2 examples that demonstrate basic physics. In this example I am going to demonstrate containment of a variable number of spheres with gravity causing deceleration.  Below you see a simple Grid which I will place a set number of spheres within.  Each sphere will be inserted into the grid at a randomized X position, within the top 20 pixels of the container.  Each sphere drop immediately and react to any collision with the container or other spheres elastically.

If you run this a few times you are bound to find it freak out. I am still in the process of tracking down why on a occasion it appears get lost and the spheres disapear.

Code: GravitationalCollisions.zip

Will developers use Silverlight?

Today I received a comment on a Poll I created which asked the question “Will Flash developers learn Silverlight”?  20% said there was no chance unless Microsoft bought Adobe.  Here is what the comment has to say.

“Nobody in their right mind will use SilverLight on the internet for a long time…..Until a user can just go to a page with SilverLight and use it, just like Flash, SilverLight won’t see the light of day on the Web….”

As one might imagine this response got me thinking, is making a user install a plugin a barrier to Silverlight adoption in the development community?  Now certainly as a Silverlight MVP I am a bit biased, but there is no way anyone can convince me that the preexistence of a 4.6MB plugin has anything to do with developer adoption.

In my day job I manage a team of developers, mostly .NET but a few experts in Flash and Flex.  Not to long ago I asked one of my senior Flash developers why he was so willing to learn Silverlight for a game project.  His response was “Why would I not want to learn another tool that makes me even more marketable”.

Bravo!  Silverlight isn’t about hunting down Flash in a global attempt to make it extinct. It’s not about one framework being better then the other.  Its about choices.  Choices push competition and competition pushed technology.   Sure Microsoft might have its own agenda, but Silverlight gives developers and interactive sites a choice. If I had the time and energy I would love to learn every programing language on every platform.  Boy would I have choices.

On 08-08-08 Silverlight 2.0 will be the technology used to broadcast over 2000 hours of the 2008 Summer Olympic games.  If the last Olympics can predict anything, then NBC should expect over 4 billion television viewers in August.  If even 10% watch some Olympics online,  you are looking at 400 million Silverlight installs.  I think it is fair to say that is a pretty nice jump on Silverlight market saturation.

Silverlight Video Player updated to display Closed Captioning

Yesterday I completed the first version of Closed Captioning support for the Silverlight 2 Video Player on CodePlex.  It definitely in an alpha phase, but with some polish it should be reliable and more usable.  Here is an image of how the captions are being displayed.


In this first version I made a decision to display closed captioning when the volume is muted, but with the right visualization we should be able to find a nice place for a ToggleButton.  Here is a list of a few other things I did to the project.

  • Updated Xml parsing to support markers with multiple types (Marker, CC, etc)
  • Converted speaker button control to ToggleButton to display a different visualization when the player is muted.
  • Linked volumeSlider to speaker button so slider drops to zero on mute and back to previous volume when mute is turned off.
  • Added a new event from mediaControl that is fired when the volume is changed.  This allows the player to control closed captioning display and not the media controller.
  • Wrote closedCaptioning UserControl that visualizes the scrolling captions.

Silverlight 2 Beta 2 Hotfix released

Last night Microsoft released a Hotfix for Silverlight 2 Beta 2.  The update is just over 6.4MB and is said to include fixes for the following:

This update for Microsoft Silverlight 2 includes stability, media streaming, and auto-update improvements as well as improved support for Firefox 3.

Here is a link to a full description of the update.

Communicating between two Silverlight objects on a single page

Not sure where I stumbled on it, but recently I watched video online where as the video was playing, a banner ad on the same page changed as the context of the video changed.  I was intrigued by the potential this technique had in interactive marketing.  As I was watching the video I was envisioning a character picking up a can of Pepsi and at that moment a corresponding banner ad somewhere else on the page switching to an ad for Pepsi.  This could be a very powerful way to create interactive calls to action.

This got me thinking about how I might duplicate that technique in Silverlight 2. I figured that the first step was to figure out a simple way communicate between two distinct Silverlight object which exists on the same page.  For this example I am going to have one SL object contain a series of Buttons, while the other SL object contains a single TextBlock.

slobjects_1


In the image above the red box I refer to as slObject1, where the blue box I refer to as slObject2.  Both of these <objects> have unique id’s and point to their own respective Silverlight Project and both have been placed in a single html file. 

In this example my slObject1 will be executing a Javascript function, which in turn will be calling an internal function inside of slObject2.  To do this I simply add a reference to the “System.Windows.Browser” namespace and call the Invoke method of the Window object.  here is what my button click handler looks like. 

slobjects_2


Once I have this defined I can now go back into my default.html file and define this Javascript function.  The function finds the appropriate html object and calls the internal function in slObject2

slobjects_3


To create my “UpdateTextBlock function I need to add a few things to the slObject2 project.  First I have to go into my App.xaml.cs file and enter the following in my Application_Startup handler.  “HtmlPage.RegisterScriptableObject("Page", page);”  This registers a managed object for scriptable access by JavaScript code.  Once registered I can create my methods as follows.

slobjects_4


That is all there is to it.  Now that I have the ability to communicate between the two SL object I can go after a more complicated implementation.

Code: SLObjects.zip

Asynchronous loading of TimelineMarkers for Silverlight Video Player

As part of the ongoing evolution of our Open Source Silverlight Video Player on CodePlex, I added the ability to asynchronously load a set of TimeLineMarkers from an XML document.  The goal was to allow users a choice between encoding there video with markers or defining those markers in an external xml file.  What I thought would be a pretty trivial task, proved to be an interesting challenge. Here is a snapshot of the Xml format.

marker_1


The first step in implementing this functionality was to download the marker Xml.  In the event that this marker file was quite large in size I decided to make the download asynchronous.  Downloading a file asynchronously required that the path to the file is absolute.  Since I have no real control over my initParams I decided to support both an absolute or relative Uri.  In the event that the path to the Xml document is relative, I make a reasonable assumption that it is located in the same location as the XAP.  As a result ,I can define my Uri with “Host.Source” as the baseUri of the Xml document.  To Download the file, I simply make a WebRequest and define an AsyncCallback to be fired when the file has completed downloading. 

Threading Considerations

In Silverlight 2 Beta 2 there was a significant change in the concurrency model used for asynchronous communications.  In Beta 1 these type of requests returned on the UI thread.  In Beta 2, when you choose to use the BeginGetResponse of the WebRequest you are telling Silverlight to use a worker thread that comes from a thread pool.  As a result, you can NOT update any user interface elements on the UI thread.  Initially I thought I would be able to use “Application.Current.RootVisual.Dispatcher” as a way to execute a delegate on the UIThread.  Unfortunately this throws a Cross Thread exception.  After explored a few options I realized that I could simply call Dispatcher.BeginInvoke(MyMethod) from within my AsyncCallback.  here is what that looked like.

void OpenStreamCompleted(IAsyncResult ar)
{
    HttpWebRequest request = ar.AsyncState as HttpWebRequest
    WebResponse response = request.EndGetResponse(ar)
 
    // Read the response into a Stream object.
    Stream responseStream = response.GetResponseStream()
 
    // Create a new StreamReader instance using the specified Stream object.
    using (StreamReader streamreader = new StreamReader(responseStream))
    {
        XElement document = XElement.Load(streamreader) 
        _externalMarkerData = (from el in document.Elements() select GetMarkerData(el)).ToList()
    }
    Dispatcher.BeginInvoke(ProcessParsedMarkerCollection)
}

As you can see above, once I have the Xml downloaded I parse it from Xml into a collection. For this I thought it would be cool to use Linq for XML.  I am always amazed at how few a lines of code I need to write to parse an Xml document with Linq.  The end product of the parse is a List<> containing a very simple custom object called “MarkerData”.  If I had chosen to move this parsing back to the UIThread I could have just created a collection of TimelineMarkers, but I thought there was no harm in having my own object to expand over time.

To get the latest source visit the project at http://www.codeplex.com/sl2videoplayer

Microsoft Most Valuable Professional (MVP)

Microsoft Most Valuable ProfessionalsI am very excited to say that today I received an email from Microsoft informing me that I have been selected as a Microsoft Most Valuable Professional (MVP) for 2008. I am not sure I genuinely deserve the honor, but I am very excited for the recognition.  My selection is within Client App Dev which affords me the opportunity to remain focus on technologies like WPF and Silverlight.

For those that know me personally, I am extremely passionate about software development and owe my professional success to Microsoft technologies. I love development, and with this honor I am inspired to be even more committed to my involvement in the Microsoft development community.  Thanks Microsoft!

Loading images in Silverlight 2

Reading through the Silverlight.net forum I still see a ton of people struggling with how to load an image procedurally. I thought it would be beneficial to included a quick sample of four different ways you can set the Image.Source property within Silverlight 2.

image_loading1




Image 1 - Resource Loaded via XAML - The easiest and most common way to load an image is to include the image in your project and set its "Build Action" to Resource. This will embedded the image within the primary assembly which gets packaged in your projects XAP file. Here is what that assembly looks like if you explore it with Reflector.

image_loading3


To reference this embedded resource within xaml, you can set the source attribute equal to the following

<Image Source="ImageSource;component/1.jpg"…>

Image 2 - Resource Loaded procedurally - In the event that you need to swap or load an images source procedurally, you can simply load up a BitmapImage via a relative URI and set the Image.Source equal to this object.

//Image 2 - Loaded via bitmap image data
// - Build Action=Resource
// - Copy to Output Directory = Do Not Copy
BitmapImage bmpImg2 = new BitmapImage()
Uri uri2 = new Uri(&quot2.jpg&quot, UriKind.Relative)
bmpImg2.UriSource = uri2
image2.Source = bmpImg2

Image 3 - Build Action = Content – If you do not desire to embed an image within your assembly, you can set its build action to “Content” and that image will be packaged within the XAP.

XAP File


//Image 3 - Load image that is included in the XAP file
// - Build action = Content
// - Copy to Output Directory = Do Not Copy
BitmapImage bmpImg3 = new BitmapImage()
Uri uri3 = new Uri(&quot/3.jpg&quot, UriKind.Relative)
bmpImg3.UriSource = uri3
image3.Source = bmpImg3

(Note: The image file name in the URI is proceeded with a front slash (/).  This is required to indicate that the image is relative to the location of the assembly.)


Image 4 - Build Action = None / Copy to Output Directory = Copy always - In the instance that you don’t want the image to be downloaded locally (packaged in XAP), you can set the “Build Action” equal to “None” and set the “Copy to Output Directory” equal to “Copy always”.  /bin directory


Using the “TestPage.html” page which is automatically generated in your projects “bin” directory you can reference the image location relatively, just as you did in sample 3.

//Image 4 - Load image that is located at some relative url
// - Build action = None
// - Copy to Output Directory = Copy always 
//      (Note: I had to manually copy the image to 
//       my web projects ClientBin directory)
BitmapImage bmpImg4 = new BitmapImage()
Uri uri4 = new Uri(&quot/4.jpg&quot, UriKind.Relative)
bmpImg4.UriSource = uri4
image4.Source = bmpImg4

Code: ImageSource.zip

Silverlight 2 Video Player pushed to CodePlex

Yesterday Tim Heuer made a great suggestion that we submit our collaboration on a  Silverlight 2 Video Player as Open Source to CodePlex. You can now find the latest source at http://www.codeplex.com/sl2videoplayer.  As we find any “undocumented features” or add new and exciting ehancments we will push these up to CodePlex.