Thursday, December 13, 2007

Forward/Rewind in Silverlight

Silverlight provides a great platform to for Video playback but Expression Media Encoder does not provide any Forward/Rewind options in Silverlight and many developers were asking about it. I thought how hard it could be so I decided to do this, I wanted to do this in VB.NET for about a month now but just kept delaying it, but when I started I finished it in about 15 minutes and I was surprised how easy it is (Now I know why Microsoft didn't bother to invest in it). I think that 15 minutes is a accomplishment so I decided not to change the  XAML or the Code. Well I had to do something to make you understand the code so spend another 10 to write comments.

Here is the XAML (Just to give you an idea, you can design your own.)

<Canvas x:Name="parentCanvas"
xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="Page_Loaded"
x:Class="VideoRewindForward.Page;assembly=ClientBin/VideoRewindForward.dll"
Width="320"
Height="205"
Background="White">
<Canvas.Resources>
<Storyboard x:Name="dummyStoryboard" Duration="0:0:0.5"/>
<Storyboard x:Name="HideMessageCanvas">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="MessageCanvas"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00.7000000" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Canvas.Resources>

<MediaElement x:Name="VideoPlayer" Souce="..." .... />
<Canvas x:Name="RewindButton" ... />
<Canvas x:Name="ForwadButton"..../>
<Canvas x:Name="PlayButton".../>
<Canvas x:Name="MessageCanvas" Opacity="0.5" Width="50" Height="18">
<Rectangle Width="50" Height="19" Fill="#FFEAEAEA"/>
<TextBlock x:Name="RewindForwardSpeed" Width="53" Height="18" TextWrapping="Wrap" Foreground="#FF000000"/>
</Canvas>
</Canvas>


And now the VB.NET Code.



Partial Public Class Page
Inherits Canvas

Private videoSpeed As Integer = 1 'Play

Public Sub Page_Loaded(ByVal o As Object, ByVal e As EventArgs)
' Required to initialize variables
InitializeComponent()
MessageCanvas.Opacity = 0
End Sub
''' <summary>
''' Play the Video
''' </summary>
''' <param name="o"></param>
''' <param name="e"></param>
''' <remarks>Calls PlayVideoAtSpeed with Speed Normal (1)</remarks>
Public Sub PlayButtonPressed(ByVal o As Object, ByVal e As EventArgs) _
Handles PlayButton.MouseLeftButtonUp
videoSpeed = 1
playVideoAtSpeed(1)
End Sub

''' <summary>
''' Handles the Event when RewindButton is pressed
''' </summary>
''' <param name="o"></param>
''' <param name="e"></param>
''' <remarks>Calls PlayThisVideo with Direction Rewind (-1)</remarks>
Private Sub RewindButtonPressed(ByVal o As Object, ByVal e As EventArgs) _
Handles RewindButton.MouseLeftButtonUp
If VideoPlayer.DownloadProgress = 1 Then
PlayThisVideo(-1)
End If
End Sub

''' <summary>
''' Handles the Event when ForwardButton is pressed
''' </summary>
''' <param name="o"></param>
''' <param name="e"></param>
''' <remarks>Calls PlayThisVideo with Direction Forward (+1)</remarks>
Private Sub ForwardButtonPressed(ByVal o As Object, ByVal e As EventArgs) _
Handles ForwadButton.MouseLeftButtonUp
If VideoPlayer.DownloadProgress = 1 Then
PlayThisVideo(1)
End If
End Sub

''' <summary>
''' Changes the direction of Forward/Rewind, Calculates new speed Check if the
''' forward/Rewind Position is Valid
''' </summary>
''' <param name="direction">-1 for Rewind, 1 for Forward</param>
''' <remarks></remarks>
Private Sub PlayThisVideo(ByVal direction As Integer)
'Change the direction, Forward/Rewind
If Math.Sign(videoSpeed) <> direction Then
videoSpeed = direction
End If
'Calculates the speed
If videoSpeed < 32 And videoSpeed > -32 Then
videoSpeed *= 2
Else
videoSpeed = 1
End If
'Calculate actual length of the video and current position.
Dim videoLength As Double = VideoPlayer.NaturalDuration.TimeSpan.TotalSeconds
Dim VideoCurrentPosition As Double = VideoPlayer.Position.TotalSeconds
'Show the speed on the canvas
ShowVideoSpeed()
'Check if the current position is not at the end(can't forward) or at the Start (can't rewind)
If VideoCurrentPosition >= 0 And VideoCurrentPosition < videoLength Then
'Play the video at speed.
playVideoAtSpeed(videoSpeed)
End If
End Sub

''' <summary>
''' This function Plays or rewinds or forwards the video, the reason this is a
''' different module and not intregrated in PlayThisVideo(direction) is that,
''' this module is also consumed when Play Button is pressed
''' </summary>
''' <param name="speed">The speed at which to play the video</param>
''' <remarks>When video is played at higher speed than 1 then the funtion pauses the video and begins
''' a dummy animation, which will iterate the forward progress until Play button is pressed.</remarks>
Private Sub playVideoAtSpeed(ByVal speed As Integer)
If speed = 1 Then
videoSpeed = speed
ShowVideoSpeed()
Else
VideoPlayer.Position = TimeSpan.FromSeconds( _
VideoPlayer.Position.TotalSeconds + speed)
VideoPlayer.Pause()
MessageCanvas.Opacity = 0.5
dummyStoryboard.Begin()
End If
End Sub

''' <summary>
''' This Module is use to iterate the froward/Rewind function.
''' </summary>
''' <param name="o"></param>
''' <param name="e"></param>
''' <remarks></remarks>
Private Sub dummyTimeline(ByVal o As Object, ByVal e As EventArgs) Handles dummyStoryboard.Completed
playVideoAtSpeed(videoSpeed)
End Sub

''' <summary>
''' ShowVideoSpeed Modules checks and shows the Rewind/Forward Speed,
''' this Module is only to show.
''' </summary>
''' <remarks>When the mode is Play, it will start the animation to hide the bar.
''' The text in this module can be replaced with </remarks>
Private Sub ShowVideoSpeed()
Dim returnString As String = ""
If videoSpeed = 1 OrElse videoSpeed = -1 Then
returnString = "Play"
VideoPlayer.Play()
HideMessageCanvas.Begin()
Else
If videoSpeed < 0 Then
returnString &= "<<" 'Can be changed with XAML or image
Else
returnString &= ">>" 'Can be changed with XAML or image
End If
returnString &= (videoSpeed * Math.Sign(videoSpeed)).ToString
End If
MessageCanvas.Opacity = 0.5
RewindForwardSpeed.Text = returnString
End Sub
End Class



Hope you enjoy. Please leave your comments.







2 comments:

adude said...

Thanks for the info! Pretty cool.

Viagra Generico said...

Nice post and great blog!! thanks for sharing!!