Posts Tagged with Slider

Silverlight 2 – Media Player with Marker support

Back in April I created a very simple Video Player in Silverlight 2 Beta 1 which Tim Heuer took to a whole new level. In his first pass he added dynamic resizing and initParams to load the video source. Then back a few weeks ago Tim brought it up to speed for Beta 2 and integrated the "VisualStateManager" to get the ToggleButton to function correctly. I love how it turned out.

One thing that I really wanted to include in my first version was control for TimelineMarkers. Unfortunately in Beta 1 I had some issues with dynamic markers, and decided to hold off until Beta 2 was released. Microsoft Expression Encoder 2 is a great tool and makes it very easy to insert markers that fire events during video playback. Markers are very simple, they define a TimeSpan of when to fire the "MarkerReached" event, and define some text that describes the marker.   In my example I will use this text as the copy for my Marker Popup.  Here is how I chose to visualize my markers in the video player.

videoplayer_c2

To achieve this effect, I created a custom UserControl called "Marker.xaml". This control contains a single animation which will fade in the text, and fade it out again after a predefined amount of time.  The control is comprised of a TextBlock and a “Arrow” path that can be moved left and right within the second row of a Grid control.  This gives me the ability to control where the Arrow visualizes in relation to my Timeline Slider control.

Based on the number of markers encoded in the video an equal number of markers will be placed in the “MediaControl”.  There position on the slider time line is determined by calculating the following:

videoplayer_c3


The position is not absolute, but close enough to where the “Thumb” in the slider control will exist at that moment the marker should popup.   Once I have placed a marker into the appropriate Grid on my MediaControl I store it in a generic Dictionary keyed off of the time it should be displayed. This allows me to very quickly find the UserControl when the Media.MarkerReached event fires or the player goes into fullscreen mode.   In the event that the user wants to play the video in fullscreen, I must reposition my markers relative to the new ActualWidth of the  sliderTimeline. 

videoplayer_c4


Here is how it all turned out. 

Code: VideoPlayerMarkers.zip

Silverlight how-to: Video Player

In my ongoing quest to work with Silverlight 2 I embarked on building my own video player using the standard MediaElement and a few of the new System Controls (ToggleButon, Slider and Button). My goal was to build a video player using no custom user controls, but instead leveraging controls styles and templates.  Here is the Video Player I ended up developing.

As you can see from my example, I was able to get a pretty clean look and feel with minimal artistic skills required.   The way my player is constructed, I have opted to encapsulate the controls for playing video into its own UserControl.  This allowed me to have a single place responsible for managing playback while allowing the main xaml page to control how the MediaElement is presented.  To give the controller access to a specific MediaElement, I pass it to my controller via a public property.

Most of the customization techniques I used are pretty well documented on MSDN.  Nonetheless, mastering controls styles was definitely a challenge. For those unfamiliar with control styles, here is an example of the xaml I used to "skin" my mute button.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<style x:key="speakerStyle" targettype="Button">
  <setter property="Template">
    <setter.value>
      <controltemplate targettype="Button">
        <grid x:name="RootElement">
          <path stretch="Fill" fill="#FFFFFFFF" data="F1 M 23.1457,
            26.5056L 23.1457,33.8944l 25.7913,33.8944l 28.8235,37.4722l 
            30.5346,37.4722l 30.5665,23.0833l 28.8995,23.0833l 25.8679,
            26.5056l 23.1457,26.5056 z " Width="7.42080116271973" 
            height="14.3889999389648"/>
        </grid>
      </controltemplate>
    </setter.value>
  </setter>
</style>

This is about as simple a skin as one can get. If I were doing this for a real client I would have certainly choose to give my button multiple states (MouseOver, Down, ect) In Silverlight 2 control states are achieved by including specific named Storyboards in your ControlTemplate resource dictionary. Each control provides a different set of pre defined states. Here is a list of the states available for a ToggleButton.

  • Checked State - The normal checked state of the control.
  • Indeterminate State - The normal indeterminate state of the control.
  • Normal State - The normal unchecked state of the control.
  • MouseOver Checked State - The state that is triggered when the mouse pointer is positioned over the checked control.
  • MouseOver Indeterminate State - The state that is triggered when the mouse pointer is positioned over the indeterminate control.
  • MouseOver Unchecked State - The state that is triggered when the mouse pointer is positioned over the unchecked control.
  • Pressed Checked State - The state that is triggered when the checked control is pressed.
  • Pressed Indeterminate State - The state that is triggered when the indeterminate control is pressed.
  • Pressed Unchecked State - The state that is triggered when the unchecked control is pressed.
  • Disabled Checked State - The state that is triggered when the checked control is disabled.
  • Disabled Indeterminate State - The state that is triggered when the indeterminate control is disabled.
  • Disabled Unchecked State - The state that is triggered when the unchecked control is disabled.

In my example I use the ToggleButton to control playback of the video.  Instead of creating two buttons, one for play and one for pause, I  choose to use a ToggleButton to combine them into one.  I display a play symbol when the video is stopped or paused, and a pause symbol when the video is playing.  The ToggleButton functions just like a checkbox, clicking it once "check’s" it while clicking it again "uncheck’s" it.   The following  is a sample of one of the Storyboards I used in skinning my ToggleButton. This animation controls which elements are visualized when a users presses the ToggleButton in an previously checked state.

1
2
3
4
5
6
7
8
9
10
11
<storyboard x:key="Pressed Checked State">
   <doubleanimation duration="0:0:0.1" 
     storyboard.targetname="playSymbol" 
     storyboard.targetproperty="Opacity" to="0" />
   <doubleanimation duration="0:0:0.1" 
     storyboard.targetname="pauseSymbol" 
     storyboard.targetproperty="Opacity" to="1" />
   <doubleanimation duration="0:0:0.1" 
    storyboard.targetname="buttonPressed" 
    storyboard.targetproperty="Opacity" to="1" />
</storyboard>

In the code above, I am ensuring that the play symbol is hidden while I show both a pause symbol and an glow image used to show the button is being pressed.

As for procedural code, all of the heavy lifting is done in the mediaControl.xaml.cs codebehind file.  The majority of code is event handlers responding to user interactions (clicks, drags,etc) or a single DispatcherTimer monitoring progress in the video playback.  My  DispatcherTimer fires a tick every 50 milliseconds which update how much time has played and visualizes on a slider how much time remains.

Code: VideoPlayer.zip