Hồi tháng 8/2008, khi tôi bắt đầu tìm hiểu về Silverlight, đọc các bài báo giới thiệu về công nghệ này, tôi thấy nhiều bài đánh giá Silverlight mạnh nhất ở streaming video với nhiều định dạng khác nhau (đặc biệt là wmv của Microsoft), tôi đã có kế hoạch viết một một chương trình chơi video bằng Silverlight xem thực hư thế nào. Khi xây dựng chương trình, có khá nhiều vấn đề thú vị nảy sinh mà tôi đã giải quyết, mong muốn viết ra để chia sẻ với mọi người từ lâu nhưng giờ mới có thời gian ngồi viết entry này, mong muốn sẽ giúp được nhiều người (nhất là newbie đang tìm hiểu về silverlight)
Bạn có thể download source project tại đây, nhưng tôi khuyên với các bạn mới học thì nên làm theo các bước tôi trình bày bên dưới, tự mình làm sẽ nhớ lâu hơn mà
Xem Demo tại http://www.hoangleminh.com/www/Silverlight/MediaPlayer.html

Phân tích các vấn đề cơ bản cần giải quyết thì một chương trình play video cơ bản cần phải có đó là :
- Play/Pause/Stop (cái này đơn giản vì MediaElement của Silverlight hỗ trợ hết cá method này)
- Thanh trượt Slider để ‘tua’ khi đang xem media và tự động slide khi video đang chạy
- Thanh trượt để điều chỉnh volume
- Hiển thị tổng thời gian và thời gian hiện tại
- Fullscreen
- Replay
Sau khi đã có một công cụ để chơi video cơ bản, việc xây dựng các hàm JavaScript tương tác với chương trình Silverlight cũng khá quan trọng
- Tạo JavaScript API như function Play, Pause, SetSouceVideo, FullScreen…
- Up chương trình lên web (vì hiện tại chưa có nhiều host hỗ trợ Framework 3.5 nên việc đưa một
chương trình Silverlight 2 lên web là khá khó khăn, tôi sẽ hướng dẫn cách dùng http://silverlight.live.com của Microsoft hỗ trợ cộng đồng lập trình Silverlight) Tôi sẽ trình bày vấn đề này ở entry sau, không thì entry này dài quá
Công việc cần làm là vậy giờ bắt tay vào giải quyết thôi!!!
1. Play, Pause
Cái này đơn giản nhất giải quyết trước, sử dụng ToogleButton
MediaElement mePlayer;
ToogleButton btnPlay;
btnPlay.Checked += new RoutedEventHandler(btnPlay_Checked);
void btnPlay_Unchecked(object sender, RoutedEventArgs e)
{
mePlayer.Pause();
btnPlay.Content = "Play";
}
void btnPlay_Checked(object sender, RoutedEventArgs e)
{
mePlayer.Play();
btnPlay.Content = "Pause";
}
2. Slider (thanh trượt theo thời gian Play video)
2.1. Slider tự động chạy khi video đang chạy
Sử dụng đối tượng timer, khi MediaElement đang ở trạng thái play thì cứ 1s lại gọi method thay đổi vị trí của thumbs trên slider
CustomSlider sliderTime; //CustomSlider là Slider tự viết kế thừa từ Slider của Silverlight, sao lại có đối tượng này thì bạn theo dõi 2.2 sẽ rõ
TextBlock tbTime; //Hiển thị current time và tổng time của video
bool isSliderTimeLock = false;
timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(50);
timer.Tick += new EventHandler(timer_Tick);
void mePlayer_CurrentStateChanged(object sender, RoutedEventArgs e)
{
if(mePlayer.CurrentState == MediaElementState.Playing)
{
timer.Start();
}
else
{
timer.Stop();
}
}
void timer_Tick(object sender, EventArgs e)
{
if((mePlayer.NaturalDuration.TimeSpan.TotalSeconds > 0) && (isSliderTimeLock == false))
{
tbTime.Text = string.Format("{0:00}:{1:00}", mePlayer.Position.Minutes, mePlayer.Position.Seconds);
sliderTime.Value = mePlayer.Position.TotalSeconds/mePlayer.NaturalDuration.TimeSpan.TotalSeconds;
}
}
2.2. Kéo chuột để chạy đến thời gian mong muốn
Cái này tưởng đơn giản nhưng làm tôi mất tới một tiếng để thực hiện, nguyên nhân là do một bug của Silverlight (từ Silverlight 2 beta 2, đến phiên bản Silverlight 2 tôi kiểm tra thấy vẫn còn, mặc dù đó là một bug đã được report và ghi nhận), số là thằng Slider có event là MouseLeftButtonUp và MouseLeftButtonDown đọc lên biết đoán ra ngay sự kiện này là gì, nhưng khổ nỗi dùng chuột kéo thả cái thumbs thì chả thấy gì cả
Cái này được tôi giải quyết bằng cách tạo CustomSlider kế thừa từ Silder và tự định nghĩa 2 sự kiện DragStarted và DragCompleted
public class CustomSlider:System.Windows.Controls.Slider
{
public CustomSlider():base()
{
DefaultStyleKey = typeof (CustomSlider);
}
public event EventHandler ThumbDragStarted;
public event EventHandler ThumbDragCompleted;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
//Set up drag event handlers
Thumb thumb = this.GetTemplateChild("HorizontalThumb") as Thumb; if (thumb != null)
{
thumb.DragStarted += new DragStartedEventHandler(thumb_DragStarted);
thumb.DragCompleted += new DragCompletedEventHandler(thumb_DragCompleted);
}
}
void thumb_DragCompleted(object sender, DragCompletedEventArgs e)
{
OnThumbDragCompleted(this, new EventArgs());
}
void thumb_DragStarted(object sender, DragStartedEventArgs e)
{
OnThumbDragStarted(this, new EventArgs());
}
public virtual void OnThumbDragStarted(object sender, EventArgs e)
{
if (ThumbDragStarted != null)
ThumbDragStarted(sender, e);
}
protected virtual void OnThumbDragCompleted(object sender, EventArgs e)
{
if (ThumbDragCompleted != null)
ThumbDragCompleted(sender, e);
}
}
Giờ tôi sẽ sử dụng cái CustomSlider này cho sliderTime (tua video) và sliderVolume (chỉnh volume)
void sliderTime_ThumbDragCompleted(object sender, EventArgs e)
{
isSliderTimeLock = false;
mePlayer.Position = TimeSpan.FromMilliseconds(mePlayer.NaturalDuration.TimeSpan.TotalMilliseconds * sliderTime.Value);
}
void sliderTime_ThumbDragStarted(object sender, EventArgs e)
{
isSliderTimeLock = true;
}
//Chỉnh volume
CustomeSlider sliderVolume;
void sliderVolume_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
mePlayer.Volume = sliderVolume.Value;
}
3. FullScreen
Sử dụng đối tượng System.Windows.Interop.SilverlightHost để thực hiện chức năng này
private System.Windows.Interop.SilverlightHost host;
Button btnFullScreen;
btnFullScreen.Click += new RoutedEventHandler(btnFullScreen_Click);
host.Content.FullScreenChanged += new EventHandler(Content_FullScreenChanged);
void btnFullScreen_Click(object sender, RoutedEventArgs e)
{
Application.Current.Host.Content.IsFullScreen = !Application.Current.Host.Content.IsFullScreen;
}
void Content_FullScreenChanged(object sender, EventArgs e)
{
if (host.Content.IsFullScreen)
{
userControl.Width = Application.Current.Host.Content.ActualWidth;
userControl.Height = Application.Current.Host.Content.ActualHeight;
mePlayer.Width = Application.Current.Host.Content.ActualWidth;
mePlayer.Height = Application.Current.Host.Content.ActualHeight;
}
else
{
userControl.Width = old_Width;
userControl.Height = old_Height;
mePlayer.Width = old_MediaWidth;
mePlayer.Height = old_MediaHeight;
}
}
Mã JavaScript để lấy ra object Silverlight nhúng trong trang web return plugin }
Ta đã có một chương trình chơi media cơ bản, giờ xây dựng JavaScript API
4. JavaScript API
Theo tư duy thông thường thì ta phải tìm cách thế nào đó để JavaScript có thể chọc được vào trong ứng dụng Silverlight để gọi các function được định nghĩa bên trọng ứng dụng Silverlight
4.1. Lấy ra object Silverlight
Trong trang MediaPlayerTestPage.aspx:
function getSilverlightObject()
{
var pluginObject = $find(""); //Xaml1 chính là ID của đối tượng Silverlight được nhúng vào
var plugin = pluginObject.get_element();
4.2. Đăng ký phương thức được phép gọi từ JavaScript
Giờ muốn sử dụng function nào trong đối tượng Silverlight thì ta phải đánh dấu đối tượng đó là [ScriptType] còn function được sử dụng là [ScriptMember], ví dụ ở đây ta muốn sử dụng function setSourceVideo() của đối tượng Page
[ScriptableType]
public partial class Page : UserControl
{
[ScriptableMember]
public void setSourceVideo(string url)
{
mePlayer.Source = new Uri(url, UriKind. RelativeOrAbsolute);
}
}
Trong mã JavaScript, muốn set lại source video ta chỉ cần gọi function setSouceVideo(string url) và truyền link video vào
function loadSource()
{
var pluginObject = $find("");
var plugin = pluginObject.get_element();
var url = “TestVideo.wmv”;
plugin.Content.mediaPlayer.setSourceVideo(url);
}
Xong, tương tự bạn có thể tự viết các JavaScript API như Play, Pause, Replay, Mute…
5. VisualStateManager
Trong project cũ viết trên Silverlight 2 beta 2 tôi có làm cả cái VisualStateManager thêm một số hiệu ứng di chuyển cho đẹp, nhưng khi update lên Silverlight 2 thì có nhiều thay đổi ở việc quản lý cái VisualState này nên tôi phải xóa hết đi, thế cũng tốt, đỡ rối mắt cho những người mới học, với ai muốn sourcecode của project có cả visual state này cho Silverlight 2 thì email cho tôi minh.hl86@gmail.com
Ở entry sau, tôi sẽ trình bày cách để đưa được một ứng dụng Silverlight 2 lên web và nhúng vào blog hay đâu đó và cả cách để treaming một video sử dụng dịch vụ miễn phí của Microsoft dành cho các nhà phát triển Silverlight http://silverlight.live.com