Tuesday, December 23, 2008

Simple Video Hosting with F# and Silverlight 2

I use to hate household maintenance projects such as replacing a leaky faucet or fixing a clogged water pipe.  I typically get frustrated because I would run into problems disassembling the plumbing components or find out that I don’t have the right tools to reassemble the plumbing components.  Lately, however, I have had much more success with my household plumbing projects.  When my kitchen faucet broke, I had a relatively painless experience in replacing the hardware.  I attribute this painless experience to the fact that I followed a video tutorial instead of printed material and come to appreciate the power and benefits of a video tutorial.

And similarly, I find myself looking for videos tutorials when it comes learning about complex technologies.  Lately, I have looked at SharePoint video tutorials and found them immensely helpful.  This got me interested in how finding out easy it is to host video content in Silverlight 2.  The answer is that it’s extremely easy and here’s a simple F# implementation of a video player in Silverlight 2.


#light
namespace SilverLightFSharp
open System
open System.Windows
open System.Windows.Controls
open System.Windows.Controls.Primitives
open System.Windows.Data
open System.Windows.Media
open List

// Simple Video Player Example in Silverlight 2 with F#
type MyPage = class
inherit UserControl

new () as this = {} then

this.Width <- 400.0
this.Height <- 400.0

let textbox = new TextBox(TextAlignment =TextAlignment.Center,
VerticalAlignment=VerticalAlignment.Top,
Text="Silverlight Video Example")

let media = new MediaElement(VerticalAlignment=VerticalAlignment.Center,
HorizontalAlignment=HorizontalAlignment.Center,
Width=400.0,Height=300.0)



let playButton = new Button(Content="Play")
let pauseButton = new Button(Content="Pause")
let stopButton = new Button(Content="Stop")

playButton.Click.Add(fun _ -> media.Play())
pauseButton.Click.Add(fun _ -> media.Pause())
stopButton.Click.Add(fun _ -> media.Stop())

let createGrid numrows numcols =
let grid = new Grid()
[1..numrows] |> iter (fun _ ->
new RowDefinition(Height=GridLength.Auto) |> grid.RowDefinitions.Add)
[1..numcols] |> iter (fun _ ->
new ColumnDefinition(Width=GridLength.Auto) |> grid.ColumnDefinitions.Add)
grid


let addTo (grid:Grid) item row column =
grid.Children.Add(item)
Grid.SetRow(item,row)
Grid.SetColumn(item,column)

let grid = createGrid 1 3

addTo grid playButton 0 0
addTo grid pauseButton 0 1
addTo grid stopButton 0 2

media.Source <- new Uri("test.wmv",UriKind.Relative)

media.DownloadProgressChanged.Add(fun e ->
let percentage = media.DownloadProgress*100.0
let status = (Printf.sprintf "%3.2f percent done" percentage)
textbox.Text <-status)

let stack = new StackPanel(Background=new SolidColorBrush(Colors.White))


textbox |> stack.Children.Add
media |> stack.Children.Add
grid |> stack.Children.Add

this.Content <- stack
end

type MyApp = class
inherit Application

new () as this = {} then
this.Startup.Add(fun _ -> this.RootVisual <- new MyPage())

end

In order to get this to work, I had to add system.dll and System.Core.dll to the .xap file. Make sure you grab these dll files from the Silverlight 2 SDK and not from the .Net Framework.

I had a request to post the .xap file and here are they are. The zip files contain both the source file along with the .xap and testpage.html file that is deployed on the server.  The deployment items are in the webdeploy folder of the zip file. The file simplebutton.zip is the source and deployment content for the previous post the file simplevideo.zip is the source and deployment content for this post.

simplebutton.zip

simplevideo.zip