MediaElement States in Silverlight

The current state of a MediaElement (Buffering, Closed, Error, Opening, Paused, Playing, or Stopped) can have an impact on users who consume your media. For example, if a user is attempting to view a large video, the MediaElement will likely remain in a state of Buffering for a significant amount of time. In this case, you would want to provide some clue in your user interface (UI) that the media cannot be played yet. When buffering is over, you would want to indicate that the media can now be played. You can detect these MediaElement states by using the CurrentState property and detect state changes by using the CurrentStateChanged event. This overview covers the use of these APIs and provides information about the transitions between the different MediaElement states.

This topic contains the following sections:

  • Using CurrentState and CurrentStateChanged  
  • State Transition Table

Using CurrentState and CurrentStateChanged

The following example demonstrates one way to display the CurrentState of a MediaElement. It creates a MediaElement and several buttons for controlling media playback. To display the current state of the MediaElement, the example registers for the CurrentStateChanged event and uses an event handler to update a TextBlock.

XAML
<Canvas 
  xmlns="https://schemas.microsoft.com/client/2007"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  Width="300" Height="300">
  <MediaElement 
    x:Name="media" 
    Source="xbox.wmv" 
    CurrentStateChanged="media_state_changed" 
    Width="300" Height="300"/>
  <!-- Stops media playback.-->
  <Canvas MouseLeftButtonDown="media_stop"
    Canvas.Left="10" Canvas.Top="265">
    <Rectangle Stroke="Black"
      Height="30" Width="55" RadiusX="5" RadiusY="5">
      <Rectangle.Fill>
        <RadialGradientBrush GradientOrigin="0.75,0.25">
          <GradientStop Color="Orange" Offset="0.0" />
          <GradientStop Color="Red" Offset="1.0" />
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
    <TextBlock Canvas.Left="5" Canvas.Top="5">stop</TextBlock>
  </Canvas>
  <!-- Pauses media playback. -->
  <Canvas MouseLeftButtonDown="media_pause"
    Canvas.Left="70" Canvas.Top="265">
    <Rectangle Stroke="Black"
      Height="30" Width="55" RadiusX="5" RadiusY="5">
      <Rectangle.Fill>
        <RadialGradientBrush GradientOrigin="0.75,0.25">
          <GradientStop Color="Yellow" Offset="0.0" />
          <GradientStop Color="Orange" Offset="1.0" />
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
    <TextBlock Canvas.Left="5" Canvas.Top="5">pause</TextBlock>
  </Canvas>
  <!-- Begins media playback. -->
  <Canvas MouseLeftButtonDown="media_begin"
    Canvas.Left="130" Canvas.Top="265">
    <Rectangle Stroke="Black" RadiusX="5" RadiusY="5"
      Height="30" Width="55">
      <Rectangle.Fill>
        <RadialGradientBrush GradientOrigin="0.75,0.25">
          <GradientStop Color="LimeGreen" Offset="0.0" />
          <GradientStop Color="Green" Offset="1.0" />
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
    <TextBlock Canvas.Left="5" Canvas.Top="5">play</TextBlock>
  </Canvas>
  <TextBlock
    Canvas.Left="190" Canvas.Top="265"
    FontSize="12">CurrentState:</TextBlock>
  <TextBlock 
    x:Name="mediaStateTextBlock"
    Canvas.Left="190" Canvas.Top="280"
    FontSize="12"></TextBlock>
</Canvas>
JavaScript
function media_stop(sender, args)
{
    sender.findName("media").stop();
}
function media_pause(sender, args)
{
    sender.findName("media").pause();
}
function media_begin(sender, args)
{
    sender.findName("media").play();
}
function media_state_changed(sender, args)
{
    var mediaStateTextBlock = 
    sender.findName("mediaStateTextBlock");
    var media = sender.findName("media");
    mediaStateTextBlock.Text = media.CurrentState;
}

Note   The CurrentStateChange event may not behave as expected. When state changes rapidly, events might be coalesced into a single firing of the event. For example, the CurrentState property might have switched from Playing to Buffering and back to Playing so rapidly that only a single CurrentStateChanged event was raised, in which case the property will not appear to have changed values. Also, your application should not assume an order in which the events occur, particularly for the transient states such as Buffering. One of the transient states may have been skipped over in event reporting because it happened so rapidly.

State Transition Table

The following table summarizes the different states the MediaElement can be in. These states correspond to the enumeration values of the MediaState enumeration.

Enumeration Values

Value Description
Buffering The MediaElement is loading the media for playback. Its Position does not advance during this state. If the MediaElement was already playing video, it continues to display the last displayed frame.
Closed The MediaElement contains no media. The MediaElement displays a transparent frame.
Opening The MediaElement is validating and attempting to open the Uniform Resource Identifier (URI) specified by its Source property.
Paused The MediaElement does not advance its Position. If the MediaElement was playing video, it continues to display the current frame.
Playing The MediaElement is playing the media specified by its source property. Its Position advances forward.
Stopped The MediaElement contains media, but it is not playing or paused. Its Position is 0 and does not advance. If the loaded media is video, the MediaElement displays the first frame.

The following table summarizes these MediaElement states versus the actions taken on the MediaElement (for example, Play method called, Pause method called, and so on).

  Source set Play() Pause() Stop() Seek() Default exit condition
Closed (default) Opening Not specified Not specified Not specified Not specified  
Opening Opening (new source) Not specified Not specified Not specified Not specified If source is valid:
Buffering (if AutoPlay == true)
Stopped (if AutoPlay == false)
(MediaOpened)

If source is invalid: Opening (MediaFailed)
Buffering Opening Playing Paused Stopped Buffering (new position) BufferingTime is reached: Playing
Playing Opening No-op Paused Stopped Buffering (new position) EOS: Stopped (live) || Paused (MediaEnded)

EOB: Buffering
Paused Opening Buffering No-op Stopped Paused (new position)  
Stopped Opening Buffering Paused No-op Paused (new position)  

As you can see in the previous table, the state that is available to the MediaElement depends on its current state. For example, for a MediaElement that is currently in the state of Playing, if the source of the MediaElement is changed, the state changes to Opening; if the Play method is called, nothing happens (no-op); if the Pause method is called, the state changes to Paused, and so on.

Note   Avoid "Not Specified" states. For example, you should not call the Play method while the media is in the Opening state. To avoid this, you could check the CurrentState of the MediaElement before allowing Play to be called.

The following notes pertain to scenarios from the previous table. Note that the scenario Buffering/Play corresponds to the MediaElement being in a state of Buffering, and then the Play method is called.

  • Buffering/Play: This scenario results in MediaElement going into the Playing state so that the user can leave the Buffering state sooner than the BufferingTime specifies.
  • Playing/Seek: This scenario results in Buffering to ensure that enough of the video stream has been downloaded.
  • [Paused or Stopped]/Play: This scenario results in Buffering to ensure that enough of the media file has been downloaded.

See Also

Audio and Video Overview
Supported Media Formats and Protocols
Overviews and How-to Topics