Silverlight introduktion - en silverlight video-afspiller.
Følg med i silverlight serien:
Introduktion
Introduktion del 2
del 3, XAML
del 4, XAML
del 5, XAML
del 6, XAML
del 7, XAML
del 8, Events
Silverlight links (opdateres hele tiden)
Hvis du ikke kender til Silverlight men har hørt en masse om det, vil jeg anbefale dig at læse de tidligere blogposts omkring hvad SilverLight 2.0. Du finder listen af hidtige post foroven.
Det er nemt at have med både video og billeder at gøre i Silverligt, du kan sagtens afspille en video uden at skulle udvikle din egen afspiller, men du kan også sagtens gøre det sværere for dig selv ved rent faktisk at udvikle den selv. Det er pærelet og kræver kun lidt hovedregning og .NET kendskab.
Hvis du starter med at åbne din Visual Studio 2008 og vælger at lave et Silverlight projekt, tilføjer det test website du så sødt bliver spurgt om, og højreklikker på den xaml fil der hedder Pag. Så vælger du at åbne den i Expression blend (højre klik på den) og der ser du den hvide og tomme design flade som nu skal benyttes ved at tegne et par kontroller og konfigurer disse.
Expression encoder hedder det værktøj der kan encode video til Silverlight. I encoder værktøjet kan du vælge en template videoen skal embeddes i og den template liste er mere end udemærket, for mulighederne er mange og hvis du ikke har tid eller lyst til selv at gå i krig så bruger du bare en af dem.
Jeg har allerede en video som er encoded til Silverlight og nu vil jeg altså gerne have den afspillet i en browser ved hjælp af det lille Silverlight plugin som du sikkert allerede har installeret. Ellers kan du finde det her og hvis du har mac kan du finde det her.
Let's get crackin'
Vi tager det oppe fra og ned. I vores Page laver vi først lige noget XAML markup og den skal se således ud:
<UserControl x:Class="CodanDemo.Page"
xmlns="https://schemas.microsoft.com/client/2007"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
Width="1200" Height="1000" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid x:Name="LayoutRoot" Background="White">
<MediaElement x:Name="mediaPlayer" AutoPlay="False" Margin="8,8,8,128.800003051758" Source=https://localhost:25997/PlayerDemo_Web/kfp_trlr1_wm_1500.wmv Volume="0"/>
<Button Height="26" x:Name="PlayPause" Click="StartPause_Click" HorizontalAlignment="Left" Margin="8,0,0,255.800003051758" VerticalAlignment="Bottom" Width="96" />
<Button Height="26" Width="96" Click="Stop_Click" HorizontalAlignment="Left" Margin="124.5,0,0,255.800003051758" VerticalAlignment="Bottom" Content="Stop" d:LayoutOverrides="Width"/>
<Slider Height="26" x:Name="movieSlider" ValueChanged="MovieSlider_ValueChanged" HorizontalAlignment="Left" Margin="235,0,0,255.800003051758" VerticalAlignment="Bottom" Width="193"/>
<Slider Height="26" x:Name="volumeSlider" ValueChanged="Volume_ValueChanged" HorizontalAlignment="Left" Margin="415,0,0,229.800003051758" VerticalAlignment="Bottom" Width="102" RenderTransformOrigin="0.5,0.5">
<Slider.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="269.784"/>
<TranslateTransform/>
</TransformGroup>
</Slider.RenderTransform>
</Slider>
<TextBox Height="36.8" x:Name="debugBox" HorizontalAlignment="Left" Margin="104,0,0,193" VerticalAlignment="Bottom" Width="231" Text=""/>
</Grid>
</UserControl>
Lad være med at blive forvirret for ovenstående er faktisk uhyre simpelt, men det tror jeg godt kan se allerede.
Læg mære til de events vi gerne vil lytte på og de navne kontrollerne har fået ved hjælp af x:Name.
Code-behind
public partial class Page : UserControl
{
private double totalSecondsOfMovie;
private DispatcherTimer timer = new DispatcherTimer();
public Page()
{
InitializeComponent();
timer.Interval = TimeSpan.FromMilliseconds(100);
timer.Tick += new EventHandler(timer_Tick);
this.Loaded += new RoutedEventHandler(Page_Loaded);
mediaPlayer.MediaOpened += new RoutedEventHandler(mediaPlayer_MediaOpened);
}
private void mediaPlayer_MediaOpened( object sender, RoutedEventArgs e )
{
totalSecondsOfMovie = mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds;
}
private void Page_Loaded( object sender, RoutedEventArgs e )
{
PlayPause.Content = "Play";
mediaPlayer.IsMuted = false;
}
private void timer_Tick( object sender, EventArgs e )
{
debugBox.Text = String.Format("{0:00}:{1:00}", mediaPlayer.Position.Minutes, mediaPlayer.Position.Seconds);
movieSlider.Value = ( ( mediaPlayer.Position.TotalSeconds / mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds ) * 10 );
}
private void Stop_Click( object sender, RoutedEventArgs e )
{
mediaPlayer.Stop();
PlayPause.Content = "Play";
movieSlider.Value = 0.0;
volumeSlider.Value = 0.0;
}
private void StartPause_Click( object sender, RoutedEventArgs e )
{
if ( mediaPlayer.CurrentState == MediaElementState.Playing ) {
timer.Stop();
mediaPlayer.Pause();
PlayPause.Content = "Play";
} else if ( mediaPlayer.CurrentState == MediaElementState.Paused || mediaPlayer.CurrentState == MediaElementState.Stopped ) {
timer.Start();
PlayPause.Content = "Pause";
mediaPlayer.Play();
}
}
private void MovieSlider_ValueChanged( object sender, RoutedPropertyChangedEventArgs<double> e )
{
double slideToPosition = e.NewValue;
if ( ( ( mediaPlayer.Position.TotalSeconds / mediaPlayer.NaturalDuration.TimeSpan.TotalSeconds ) * 10 ) != slideToPosition ) {
int seconds = Convert.ToInt32(slideToPosition * totalSecondsOfMovie) / 10;
mediaPlayer.Position = new TimeSpan(0, 0, seconds);
}
}
private void Volume_ValueChanged( object sender, RoutedPropertyChangedEventArgs<double> e )
{
mediaPlayer.Volume = e.NewValue / 10;
}
}
Forklaring
I vores XAML definere vi 6 kontroller: 2 Buttons, 2 Sliders, 1 MediaElement og en TextBox.
På begge Buttons lytter vi på Click eventen (se StartPause_Click og Stop_Click) og laver så et check på lidt forskelligt. Det meste af det siger sig selv bortset fra én ting, nemlig timeren. Den kommer jeg tilbage til om lidt.
De 2 Sliders har vi ikke snakket om før, men det er princippet bare 2 indikatorer der for det første skal fortælle os noget omkring hvor langt vores film er nået og hvad volumen er. Der er yderligere lavet funktionalitet til at kunne skrue op og ned for volumen samt spole i filmen. Det er her vores hovedregning kommer ind i billeder. Hvis du kigger på MovieSlider_ValueChanged og Volume_ValueChanged så kan du se at der er bliver foretaget et par simple regnestykker. En Slider kan variere fra værdien 0 til 1 og derfor har vi været nødt til at lave disse regnestykker så man spole samt ændre volumen lidt mere nøjagtigt.
Vores MediaElement er til videoen og på den lytter vi også på en event: mediaPlayer_MediaOpened.
vores TextBox bruger til at udskrive hvor langt videoen er kommet, så det er også en slags indikator i dette tilfælde. Jeg har kaldt TextBoxen debugText fordi jeg også bruger den til at outputte væsentlige værdier når jeg har testet playeren og koden.
Det sidste som både er det mest spændende og irreterende ved denne kode er vores DispatcherTimer i toppen. Silverlight har ingen indbygget funktionalitet til at vise os hvor langt vores video er kommet, så det har vi været nødt til selv at kode.
Vores DispatherTimer bliver i dette tilfælde sat til at køre med et interval på hvor langt vores video er kommet udfra det regnestykke der er i timer_Tick. Vi kan tænde og slukke for vores timer som vi har lyst og den husker selv sit state så vi ikke skal resette hver gang vi starter eller stopper filmen.
Det hele er meget nemmere når du selv har fingrene i koden, så derfor synes jeg du skal downloade koden her.
Comments
Anonymous
July 04, 2008
PingBack from http://blog.a-foton.ru/2008/07/silverlight-introduktion-en-silverlight-video-afspiller/Anonymous
July 05, 2008
amazing - not a clue which nordic langyuage this is, but I could work it all out from the code.Anonymous
July 08, 2008
Interessant indlæg - jeg skal da have lavet min egen Silverlight player!