# Monday, June 08, 2009

SLMedia le player Photo / Video de SLExtensions

Les librairies SLMedia regroupent tout ce qu'il vous faut pour gérer vos galeries photos et vidéo. Ces librairies sont séparées en plusieurs dlls gérant chacune un type de média.

  • SLMedia.Core : Librairie centrale prenant en charge les fonctions communes.
  • SLMedia.Picture : Librairie vous permettant de réaliser des slideshows d’images.
  • SLMedia.Deepzoom : Librairie vous permettant d’afficher des galeries deepzoom de vos images.
  • SLMedia.Video : Librairie gérant les galeries vidéos.
  • SLMedia.SmoothStreaming : Gestion des vidéos en Smooth Streaming

Création d’un player video avec SLMedia

La réalisation d’un player avec SLMedia repose sur les concepts de Binding et de Behavior. Les Bindings vont vous servir à lier les informations provenant du controller (ici un VideoController) et les différents éléments graphiques qui vont vous permettre d’afficher et d’agir sur votre vidéo.

MediaController

Cette classe appartenant à SLMedia.Core sert de base au VideoController. Elle regroupe les fonctionnalités communes aux différents controllers.

  • Gestion de la playlist (Next, Previous, IsPlaying, SelectedItem)
  • Gestion du fullscreen (IsFullscreen)
  • Gestion des progressions pour les slideshow / videos (Position, Duration)
  • Etc..

VideoController

Cette classe hérite du MediaController et lui rajoute des fonctions spécifiques pour la vidéo.

  • MediaElement
  • Buffering
  • Support de différentes source par les VideoAdapter

Etape 1 : Affichage d’une video de la playlist

Dans votre page xaml, référencez le namespace correspondant à SLMedia.Video et ajouter le VideoController aux ressources.

<UserControl x:Class="VideoPlayer1.Page"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:slvideo="clr-namespace:SLMedia.Video;assembly=SLMedia.Video"

   >

    <UserControl.Resources>

        <slvideo:VideoController x:Name="controller" />

    </UserControl.Resources>

Ensuite posez un MediaElement et associez sa source avec la propriété CurrentItem de notre controller. Le CurrentItem sera du type IMediaItem et possèdera donc une propriété SourceUri contenant l’url de la vidéo à afficher.

    <Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource controller}}" >

        <MediaElement x:Name="mediaelement"

                    Source="{Binding Path=CurrentItem.SourceUri}"

                    />

    </Grid>

Il ne reste plus qu’à renseigner un nouvel item dans la playlist et de le sélectionner pour que la video se lancer.

using SLMedia.Video;

using SLMedia.Core;

 

namespace VideoPlayer1

{

    public partial class Page : UserControl

    {

        public Page()

        {

            InitializeComponent();

            controller = (VideoController)Resources["controller"];

 

            this.Loaded += new RoutedEventHandler(Page_Loaded);

        }

 

        void Page_Loaded(object sender, RoutedEventArgs e)

        {

            controller.Playlist.Add("http://labs.ucaya.com/lake.wmv");

            controller.Next();

        }

    }

}

Pour rendre complétement opérationnel notre videocontroller, nous devons lui indiquer quel est le MediaElement qui affiche la vidéo. De cette manière il pourra récupérer les états de lecture, de progression et de buffering. Nous allons également lier quelques propriétés supplémentaires qui nous permettrons de tout contrôler depuis le VideoController.

        <MediaElement x:Name="mediaelement"

                    Source="{Binding Path=CurrentItem.SourceUri}"

                    slvideo:VideoController.MediaElement="{StaticResource controller}"

                    IsMuted="{Binding Path=IsMuted}"

                    Volume="{Binding Path=Volume}"

                    AutoPlay="{Binding Path=AutoPlay}"   

                    />

Etape 2 : Lecture / Pause

L’état lecture / pause est géré dans notre controller par la propriété IsPlaying. Un binding entre une checkbox et cette propriété permetra de contrôler facilement l’état de lecture.

        <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Background="#50000000" Margin="30">

            <CheckBox IsChecked="{Binding Path=IsPlaying, Mode=TwoWay}" />

        </StackPanel>

Etape 3 : Position / Durée

Un slider Bindé sur les propriétés Duration et Position fera l’affaire. Les propriétés Duration et Position étant du type TimeSpan, nous allons utiliser un IValueConverter pour transformer la valeur en Double.

<UserControl x:Class="VideoPlayer1.Page"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:slvideo="clr-namespace:SLMedia.Video;assembly=SLMedia.Video"

   xmlns:slec="clr-namespace:SLExtensions.Controls;assembly=SLExtensions.Controls"

   xmlns:sled="clr-namespace:SLExtensions.Data;assembly=SLExtensions.Data"

   Foreground="White"

    >

    <UserControl.Resources>

        <slvideo:VideoController x:Name="controller" />

        <sled:TimeSpanConverter x:Name="timeSpanConverter"/>

    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource controller}}">

        <MediaElement x:Name="mediaelement"

                    Source="{Binding Path=CurrentItem.SourceUri}"

                    slvideo:VideoController.MediaElement="{StaticResource controller}"

                    IsMuted="{Binding Path=IsMuted}"

                    Volume="{Binding Path=Volume}"

                    AutoPlay="{Binding Path=AutoPlay}"   

                    />

        <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Background="#50000000" Margin="30">

            <CheckBox IsChecked="{Binding Path=IsPlaying, Mode=TwoWay}" />

            <slec:Slider Maximum="{Binding Converter={StaticResource timeSpanConverter}, Path=Duration}"

                        MoveValue="{Binding Converter={StaticResource timeSpanConverter}, Mode=TwoWay, Path=Position}"

                        Width="200" Margin="20,0,0,0"

                        />

            <TextBlock Text="{Binding Converter={StaticResource timeSpanConverter}, Path=Position}"

                    Margin="20,0,0,0"/>

            <TextBlock Text=" / " />

            <TextBlock Text="{Binding Converter={StaticResource timeSpanConverter}, Path=Duration}" />

        </StackPanel>

    </Grid>

</UserControl>

Si vous utilisez le slider de base de silverlight, vous noterez des problèmes lorsque vous déplacez le curseur. Pendant que vous déplacez le curseur, la propriété Value peut être remise à jour par le binding et le curseur donne l’impression de sauter.

Etape 4 : Volume

De même que pour la position, nous allons utiliser un slider pour le volume et une checkbox pour le mute

            <CheckBox IsChecked="{Binding Path=IsMuted, Mode=TwoWay}" Margin="20,0,0,0"/>

            <Slider Maximum="1" SmallChange="0.1" LargeChange="0.1"

                   Value="{Binding Path=Volume, Mode=TwoWay}" Width="50" />

Etape 5 : Buffering - Downloading

Encore du binding

            <TextBlock Text="Buffering:" />

            <TextBlock Text="{Binding Path=BufferingProgress, Mode=TwoWay, Converter={StaticResource strConverter}, ConverterParameter='{0:p}'}" />

            <Slider Maximum="1"

                   Value="{Binding Path=BufferingProgress, Mode=TwoWay}" Width="50" IsHitTestVisible="False" Margin="5,0,0,0"/>

 

            <TextBlock Text="Downloading:" Margin="20,0,0,0"/>

            <TextBlock Text="{Binding Path=DownloadProgress, Mode=TwoWay, Converter={StaticResource strConverter}, ConverterParameter='{0:p}'}" />

            <Slider Maximum="1"

                   Value="{Binding Path=DownloadProgress, Mode=TwoWay}" Width="50" IsHitTestVisible="False"

                   Margin="5,0,0,0"/>

Etape 6 : Gestion des états visuels

Le VideoController centralise les propriétés de notre player video. Il est possible de changer l’état visuel de nos contrôles en fonction des propriétés du VideoController. Nous allons utiliser le behaviors fournis par SLExtensions pour mapper ces propriétés à nos VisualStates.

<UserControl x:Class="VideoPlayer1.Page"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:slvideo="clr-namespace:SLMedia.Video;assembly=SLMedia.Video"

   xmlns:slec="clr-namespace:SLExtensions.Controls;assembly=SLExtensions.Controls"

   xmlns:sled="clr-namespace:SLExtensions.Data;assembly=SLExtensions.Data"

 

   xmlns:inter="clr-namespace:Microsoft.Expression.Interactivity;assembly=Microsoft.Expression.Interactivity"

   xmlns:slint="clr-namespace:SLExtensions.Interactivity;assembly=SLExtensions.Interactivity"

 

   xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"

 

   Foreground="White"

    >

    <UserControl.Resources>

        <slvideo:VideoController x:Name="controller" />

        <sled:TimeSpanConverter x:Name="timeSpanConverter"/>

        <sled:StringFormatConverter x:Name="strConverter"/>

    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" DataContext="{Binding Source={StaticResource controller}}">

        <vsm:VisualStateManager.VisualStateGroups>

            <vsm:VisualStateGroup x:Name="PlayingStates">

                <vsm:VisualStateGroup.Transitions>

                    <vsm:VisualTransition GeneratedDuration="00:00:00.3000000"/>

                </vsm:VisualStateGroup.Transitions>

                <vsm:VisualState x:Name="Playing">

                    <Storyboard>

                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="stackPanel" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">

                            <SplineColorKeyFrame KeyTime="00:00:00" Value="#5039FF00"/>

                        </ColorAnimationUsingKeyFrames>

                    </Storyboard>

                </vsm:VisualState>

                <vsm:VisualState x:Name="Paused">

                    <Storyboard>

                        <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="stackPanel" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">

                            <SplineColorKeyFrame KeyTime="00:00:00" Value="#50D56700"/>

                        </ColorAnimationUsingKeyFrames>

                    </Storyboard>

                </vsm:VisualState>

            </vsm:VisualStateGroup>

        </vsm:VisualStateManager.VisualStateGroups>

        <inter:Interaction.Behaviors>

            <slint:MapState Source="{StaticResource controller}" Property="IsPlaying" >

                <slint:MapStateMapping StateName="Playing" Value="true"/>

                <slint:MapStateMapping StateName="Paused" Value="false"/>

            </slint:MapState>

        </inter:Interaction.Behaviors>

 

        <MediaElement x:Name="mediaelement"

                    Source="{Binding Path=CurrentItem.SourceUri}"

                    slvideo:VideoController.MediaElement="{StaticResource controller}"

                    IsMuted="{Binding Path=IsMuted}"

                    Volume="{Binding Path=Volume}"

                    AutoPlay="{Binding Path=AutoPlay}"   

                    />

        <StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Background="#50000000" Margin="30" x:Name="stackPanel">

            <CheckBox IsChecked="{Binding Path=IsPlaying, Mode=TwoWay}" />

            <slec:Slider Maximum="{Binding Converter={StaticResource timeSpanConverter}, Path=Duration}"

                        MoveValue="{Binding Converter={StaticResource timeSpanConverter}, Mode=TwoWay, Path=Position}"

                        Width="200" Margin="20,0,0,0"

                        />

            <TextBlock Text="{Binding Converter={StaticResource timeSpanConverter}, Path=Position}"

                    Margin="20,0,0,0"/>

            <TextBlock Text=" / " />

            <TextBlock Text="{Binding Converter={StaticResource timeSpanConverter}, Path=Duration}" />

 

            <CheckBox IsChecked="{Binding Path=IsMuted, Mode=TwoWay}" Margin="20,0,0,0"/>

            <Slider Maximum="1" SmallChange="0.1" LargeChange="0.1"

                   Value="{Binding Path=Volume, Mode=TwoWay}" Width="50" />

 

            <TextBlock Text="Buffering:" />

            <TextBlock Text="{Binding Path=BufferingProgress, Mode=TwoWay, Converter={StaticResource strConverter}, ConverterParameter='{0:p}'}" />

            <Slider Maximum="1"

                   Value="{Binding Path=BufferingProgress, Mode=TwoWay}" Width="50" IsHitTestVisible="False" Margin="5,0,0,0"/>

 

            <TextBlock Text="Downloading:" Margin="20,0,0,0"/>

            <TextBlock Text="{Binding Path=DownloadProgress, Mode=TwoWay, Converter={StaticResource strConverter}, ConverterParameter='{0:p}'}" />

            <Slider Maximum="1"

                   Value="{Binding Path=DownloadProgress, Mode=TwoWay}" Width="50" IsHitTestVisible="False"

                   Margin="5,0,0,0"/>

 

            <CheckBox IsChecked="{Binding Path=IsFullscreen, Mode=TwoWay}" Margin="20,0,0,0" Content="Fullscreen" Foreground="White"/>

 

        </StackPanel>

    </Grid>

</UserControl>

#    Comments [0] |