Mike Taulty's Blog
Bits and Bytes from Microsoft UK
Silverlight 2 - Video, Markers, XML
Mike Taulty's Blog

Mike's Badges

Follow on Twitter
View mike's profile on slideshare
Add to Technorati Favorites
CW Blog Awards

I encountered a chap the other day who was building an application which did something like this;

  1. Play a video
  2. Load a set of times and thumbnail images from an XML file.
  3. Highlight the thumbnail images at the point where the video hits the right position.

I thought this was a great example of how easy it can be to build solutions with Silverlight 2 ( regardless of whether Expression Encoder can already do some/all of this for you automatically ).

Starting with a UI, I might have;

<UserControl x:Class="SilverlightApplication12.Page"
    xmlns="http://schemas.microsoft.com/client/2007" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls">
    <Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
      <RowDefinition
        Height="7*" />
      <RowDefinition
        Height="3*" />
    </Grid.RowDefinitions>
    <MediaElement
      x:Name="media"
      Source="{Binding VideoUri}"
      HorizontalAlignment="Center"
      VerticalAlignment="Center"
      Stretch="Uniform" />
    <ListBox
      x:Name="lstPictures"
      ItemsSource="{Binding Images}"
      Grid.Row="1"
      >    
      <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
          <StackPanel
            Orientation="Horizontal"/>
        </ItemsPanelTemplate>
      </ListBox.ItemsPanel>
      <ListBox.ItemTemplate>
        <DataTemplate>
          <Image
            MaxWidth="96"
            MaxHeight="96"
            Margin="20"
            Stretch="Fill" 
            Source="{Binding}"/>
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>
  </Grid>
</UserControl>

and then I might have an XML file for my video which looks something like;

<video url="videos/video.wmv">
  <timeline>
    <marker timeInSeconds="2"
            image="images/img1.jpg"/>
    <marker timeInSeconds="4"
            image="images/img2.jpg"/>
    <marker timeInSeconds="6"
            image="images/img3.jpg"/>
  </timeline>
</video>

I want to databind as much as possible so I write some code to produce a class that suits my needs;

public class VideoInfo
  {
    // TODO: Cache results of executing these queries. Maybe.
    public Uri VideoUri
    {
      get
      {
        string url = (string)root.Attribute("url");

        return (new Uri(url, UriKind.Relative));
      }
    }
    public List<BitmapImage> Images
    {
      get
      {
        var query =
          from i in root.DescendantsAndSelf("marker")
          select new BitmapImage() {
            UriSource = new Uri((string)i.Attribute("image"), UriKind.Relative)
          };

        return (query.ToList());
      }
    }
    public void AddMarkersToMediaElement(MediaElement element)
    {
      var query =
        from i in root.DescendantsAndSelf("marker")
        select new TimelineMarker()
        {
          Time = new TimeSpan(0, 0, (int)i.Attribute("timeInSeconds")),
          Text = string.Empty,
          Type = string.Empty
        };

      foreach (var item in query)
      {
        element.Markers.Add(item);
      }
    }
    public void LoadFromXml(Uri xmlUri)
    {
      WebClient client = new WebClient();
      client.OpenReadCompleted += OnReadCompleted;
      client.OpenReadAsync(xmlUri);
    }
    void OnReadCompleted(object sender, OpenReadCompletedEventArgs e)
    {
      root = XElement.Load(XmlReader.Create(e.Result));

      if (Loaded != null)
      {
        Loaded(this, null);
      }
    }
    public event EventHandler Loaded;
    private XElement root;
  }

This just gives me a class that will load up the XML file and fire an event when it's loaded and then offers properties to my UI so that they can be databound. With that in place, I need very little code to make the application "function" such as;

  public partial class Page : UserControl
  {
    public Page()
    {
      InitializeComponent();

      this.Loaded += OnPageLoaded;
    }

    void OnPageLoaded(object sender, RoutedEventArgs e)
    {
      VideoInfo videoInfo = new VideoInfo();
      videoInfo.Loaded += OnInfoLoaded;
      videoInfo.LoadFromXml(
        new Uri("video.xml", UriKind.Relative));
    }

    void OnInfoLoaded(object sender, EventArgs e)
    {
      VideoInfo videoInfo = (VideoInfo)sender;

      this.DataContext = videoInfo;

      media.MediaOpened += (s, a) =>
        {
          videoInfo.AddMarkersToMediaElement(media);
        };

      media.MarkerReached += (s, a) =>
      {
        lstPictures.SelectedIndex++;
      };
    }
  }

 

and we're "in business" :-)


Posted Wed, Apr 16 2008 6:57 AM by mtaulty
Filed under:

Comments

Silverlight 2 - Video, Markers, XML wrote Silverlight 2 - Video, Markers, XML
on Thu, Apr 17 2008 12:30 AM
&lt;p&gt;I encountered a chap the other day who was buil
(C) Mike Taulty, 2009. All rights reserved. The information in this weblog is provided "AS IS" with no warranties, and confers no rights. This weblog does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion. Inappropriate comments will be deleted at the authors discretion. All code samples are provided "AS IS" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems