闲来无事,倒腾了一个简单的silverlight视频播放器
近二日闲来无事,把silverlight的官方文档瞅了瞅,倒腾了一个简单的视频播放器,顺便也测试了下能否播放传说中的h.264,最终效果如下:
xaml代码:
后端cs代码:
http://images.24city.com/jimmy/player/default.html
布局思路:
Grid做为最外层容器,分上中下三行
第一行为视频播放窗口,同时单击视频时"暂停"遮罩层也放在这一行,只不过默认不显示而已
第二行为进度条显示区,为了方便布局,在这一行用StackPanel作子容器横向放置了二个控件(进度条和时间显示)
第三行为其它的控制按钮区,也是用StackPanel横向放置其它控件
实现的功能:
1.单击视频,暂停播放,再次单击则继续播放,原则就是利用鼠标单击事件控制Canvas的显示/隐藏以及调用MediaElement的Play(),Pause()方法
2.进度条与播放时间的同步,这里用到了Timer控件,每隔一定时间重新设置进度条的值
3.播放列表采用json字符串解析后绑定实现,同时选择列表的相关视频后,马上播放选择的视频
4.全屏功能
5.静音功能(其实还可以方便左右声道功能,只要不知道界面上怎么放,所以这一块功能没加上去)
6.缓冲以及加载进度的百分比进度显示
7.播放时,预先加载下一段视频(这一块好象效果不明显,主要是对silverlight的缓冲机制不清楚,期待大家共同探讨改进)
另:本示例中用的视频全部为mp4格式的h.264视频
其它不清楚的地方,基本上代码中都有注释
xaml代码:
1<UserControl x:Class="Test.MainPage"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5 mc:Ignorable="d">
6 <Grid x:Name="LayoutRoot" ShowGridLines="False" >
7
8 <!--Grid布局:分成三行,第一行放视频窗口,第二行为进度条,第三行为其它控制按钮-->
9 <Grid.ColumnDefinitions>
10 <ColumnDefinition Width="*"></ColumnDefinition>
11 </Grid.ColumnDefinitions>
12
13 <Grid.RowDefinitions>
14 <RowDefinition Height="*"></RowDefinition>
15 <RowDefinition Height="22"></RowDefinition>
16 <RowDefinition Height="25"></RowDefinition>
17 </Grid.RowDefinitions>
18
19
20 <!--视频播放控件-->
21 <MediaElement x:Name="media" Source="" Grid.Row="0" Grid.Column="0" CurrentStateChanged="Media_State_Changed" MediaEnded="media_MediaEnded" Cursor="Hand" MouseLeftButtonDown="media_MouseLeftButtonDown" BufferingProgressChanged="media_BufferingProgressChanged" DownloadProgressChanged="media_DownloadProgressChanged"></MediaElement>
22
23 <!--这里用一个Canvas来实现暂停时的遮盖效果-->
24 <Canvas Background="#AAFAEBD7" Grid.Row="0" Grid.Column="0" Cursor="Hand" x:Name="canvas_Pause" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" >
25 <Ellipse Height="200" Width="200" Stroke="AliceBlue" StrokeThickness="10" Canvas.Left="140" Canvas.Top="80"></Ellipse>
26 <Path Stretch="Fill" Stroke="AliceBlue" StrokeThickness="10" Height="98" Width="10" UseLayoutRounding="False" Canvas.Left="203" Canvas.Top="131" Data="M208,136 L208,224"/>
27 <Path Stretch="Fill" Stroke="AliceBlue" StrokeThickness="10" Height="98" Width="10" UseLayoutRounding="False" Canvas.Left="263" Canvas.Top="131" Data="M208,136 L208,224"/>
28
29 <TextBlock Canvas.Left="104" Canvas.Top="296" Foreground="White" >Made by 菩提树下的杨过(http://yjmyzz.cnblogs.com/)</TextBlock>
30 </Canvas>
31
32 <MediaElement x:Name="mediaBuffer" Width="0" Grid.Column="0" Grid.Row="0" BufferingTime="0:0:10" IsMuted="True" AutoPlay="True" ></MediaElement>
33
34 <!--第二行用一个StackPanel横向放了二个子控件,用于显示进度条和当前播放时间-->
35 <StackPanel Grid.Column="0" Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" >
36 <Slider Height="20" Width="370" x:Name="sliderProgress" ValueChanged="sliderProgress_ValueChanged" Cursor="Hand" ></Slider>
37 <TextBlock Text="00:00:00/00:00:00" Width="110" x:Name="txtTime"/>
38 </StackPanel>
39
40 <!--第三行同样用StackPanel横向放置其它控制按钮-->
41 <StackPanel Grid.Column="0" Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center" >
42 <Button Click="PlayMedia" Content="||" Width="25" Height="25" x:Name="btnPlay" Cursor="Hand" />
43 <Button Click="StopMedia" Content="■" Width="25" Height="25" x:Name="btnStop" Cursor="Hand"/>
44 <TextBlock x:Name="txtProgress" FontSize="12" Width="90" Text="缓冲中100%" Height="25" TextAlignment="Center" Margin="3,0" Padding="0,6,0,0" ></TextBlock>
45 <ComboBox x:Name="cboList" SelectionChanged="cboList_SelectionChanged" Height="25" Width="232">
46
47 </ComboBox>
48 <Button Content="静" Width="25" Height="25" Margin="3,0" x:Name="btnVoice" Click="btnVoice_Click" Cursor="Hand"></Button>
49 <Slider Height="25" Width="50" x:Name="sliderVoice" Maximum="1" Minimum="0" ValueChanged="sliderVoice_ValueChanged" Value="0.5" Cursor="Hand" ></Slider>
50 <Button Content="全" Width="20" Height="25" Cursor="Hand" x:Name="btnFull" Click="btnFull_Click"></Button>
51 </StackPanel>
52
53 </Grid>
54</UserControl>
55
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5 mc:Ignorable="d">
6 <Grid x:Name="LayoutRoot" ShowGridLines="False" >
7
8 <!--Grid布局:分成三行,第一行放视频窗口,第二行为进度条,第三行为其它控制按钮-->
9 <Grid.ColumnDefinitions>
10 <ColumnDefinition Width="*"></ColumnDefinition>
11 </Grid.ColumnDefinitions>
12
13 <Grid.RowDefinitions>
14 <RowDefinition Height="*"></RowDefinition>
15 <RowDefinition Height="22"></RowDefinition>
16 <RowDefinition Height="25"></RowDefinition>
17 </Grid.RowDefinitions>
18
19
20 <!--视频播放控件-->
21 <MediaElement x:Name="media" Source="" Grid.Row="0" Grid.Column="0" CurrentStateChanged="Media_State_Changed" MediaEnded="media_MediaEnded" Cursor="Hand" MouseLeftButtonDown="media_MouseLeftButtonDown" BufferingProgressChanged="media_BufferingProgressChanged" DownloadProgressChanged="media_DownloadProgressChanged"></MediaElement>
22
23 <!--这里用一个Canvas来实现暂停时的遮盖效果-->
24 <Canvas Background="#AAFAEBD7" Grid.Row="0" Grid.Column="0" Cursor="Hand" x:Name="canvas_Pause" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" >
25 <Ellipse Height="200" Width="200" Stroke="AliceBlue" StrokeThickness="10" Canvas.Left="140" Canvas.Top="80"></Ellipse>
26 <Path Stretch="Fill" Stroke="AliceBlue" StrokeThickness="10" Height="98" Width="10" UseLayoutRounding="False" Canvas.Left="203" Canvas.Top="131" Data="M208,136 L208,224"/>
27 <Path Stretch="Fill" Stroke="AliceBlue" StrokeThickness="10" Height="98" Width="10" UseLayoutRounding="False" Canvas.Left="263" Canvas.Top="131" Data="M208,136 L208,224"/>
28
29 <TextBlock Canvas.Left="104" Canvas.Top="296" Foreground="White" >Made by 菩提树下的杨过(http://yjmyzz.cnblogs.com/)</TextBlock>
30 </Canvas>
31
32 <MediaElement x:Name="mediaBuffer" Width="0" Grid.Column="0" Grid.Row="0" BufferingTime="0:0:10" IsMuted="True" AutoPlay="True" ></MediaElement>
33
34 <!--第二行用一个StackPanel横向放了二个子控件,用于显示进度条和当前播放时间-->
35 <StackPanel Grid.Column="0" Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Center" >
36 <Slider Height="20" Width="370" x:Name="sliderProgress" ValueChanged="sliderProgress_ValueChanged" Cursor="Hand" ></Slider>
37 <TextBlock Text="00:00:00/00:00:00" Width="110" x:Name="txtTime"/>
38 </StackPanel>
39
40 <!--第三行同样用StackPanel横向放置其它控制按钮-->
41 <StackPanel Grid.Column="0" Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center" >
42 <Button Click="PlayMedia" Content="||" Width="25" Height="25" x:Name="btnPlay" Cursor="Hand" />
43 <Button Click="StopMedia" Content="■" Width="25" Height="25" x:Name="btnStop" Cursor="Hand"/>
44 <TextBlock x:Name="txtProgress" FontSize="12" Width="90" Text="缓冲中100%" Height="25" TextAlignment="Center" Margin="3,0" Padding="0,6,0,0" ></TextBlock>
45 <ComboBox x:Name="cboList" SelectionChanged="cboList_SelectionChanged" Height="25" Width="232">
46
47 </ComboBox>
48 <Button Content="静" Width="25" Height="25" Margin="3,0" x:Name="btnVoice" Click="btnVoice_Click" Cursor="Hand"></Button>
49 <Slider Height="25" Width="50" x:Name="sliderVoice" Maximum="1" Minimum="0" ValueChanged="sliderVoice_ValueChanged" Value="0.5" Cursor="Hand" ></Slider>
50 <Button Content="全" Width="20" Height="25" Cursor="Hand" x:Name="btnFull" Click="btnFull_Click"></Button>
51 </StackPanel>
52
53 </Grid>
54</UserControl>
55
后端cs代码:
1using System;
2using System.Collections.Generic;
3using System.Json;
4using System.Windows;
5using System.Windows.Controls;
6using System.Windows.Input;
7using System.Windows.Interop;
8using System.Windows.Threading;
9
10namespace Test
11{
12
13
14 public partial class MainPage : UserControl
15 {
16 private DispatcherTimer _timerPlay;
17
18 //实际应用中,以下字符串可通过wcf调用获得
19 private string _medialist = "[{src:'http://task.24city.com/video/01.mp4',name:'苹果王手机第1段'},{src:'http://task.24city.com/video/02.mp4',name:'苹果王手机第2段'},{src:'http://task.24city.com/video/03.mp4',name:'苹果王手机第3段'},{src:'http://task.24city.com/video/04.mp4',name:'蔡依林-柠檬草的味道'},{src:'http://task.24city.com/video/05.mp4',name:'我也不知道是啥'},{src:'http://task.24city.com/video/06.mp4',name:'游戏宣传片段'}]";
20
21 List<MediaItem> _listMedia = null;
22
23 int _currentIndex = -1;//正在播放的元素索引
24
25
26 public MainPage()
27 {
28 InitializeComponent();
29
30 //解析Json
31 JsonValue _jsValue = JsonArray.Parse(_medialist);
32
33 if (_jsValue.Count > 0)
34 {
35 _listMedia = new List<MediaItem>(_jsValue.Count);
36
37 for (int i = 0; i < _jsValue.Count; i++)
38 {
39 _listMedia.Add(new MediaItem() { src = _jsValue[i]["src"], name = _jsValue[i]["name"] });
40 }
41
42 _currentIndex = 0;//默认从第一个开始播放
43 media.Source = new Uri(_listMedia[_currentIndex].src);
44
45 cboList.ItemsSource = _listMedia;
46 cboList.DisplayMemberPath = "name";
47 cboList.SelectedIndex = _currentIndex;
48
49
50 this._timerPlay = new DispatcherTimer();
51 this._timerPlay.Interval = new TimeSpan(0, 0, 0, 0, 100);
52 this._timerPlay.Tick += new EventHandler(timer_Tick);
53 this._timerPlay.Start();
54 }
55
56
57 App.Current.Host.Content.FullScreenChanged += new EventHandler(Content_FullScreenChanged);
58
59
60 }
61
62 /// <summary>
63 /// timer触发时,设置进度条与播放时间同步
64 /// </summary>
65 /// <param name="sender"></param>
66 /// <param name="e"></param>
67 void timer_Tick(object sender, EventArgs e)
68 {
69 this.sliderProgress.Maximum = this.media.NaturalDuration.TimeSpan.TotalSeconds;
70
71 this.sliderProgress.ValueChanged -= new RoutedPropertyChangedEventHandler<double>(sliderProgress_ValueChanged);
72
73 this.sliderProgress.Value = this.media.Position.TotalSeconds;
74
75 this.sliderProgress.ValueChanged += new RoutedPropertyChangedEventHandler<double>(sliderProgress_ValueChanged);
76
77 this.txtTime.Text = media.Position.Hours.ToString().PadLeft(2, '0') + ":" + media.Position.Minutes.ToString().PadLeft(2, '0') + ":" + media.Position.Seconds.ToString().PadLeft(2, '0') + "/" + media.NaturalDuration.TimeSpan.Hours.ToString().PadLeft(2, '0') + ":" + media.NaturalDuration.TimeSpan.Minutes.ToString().PadLeft(2, '0') + ":" + media.NaturalDuration.TimeSpan.Seconds.ToString().PadLeft(2, '0');
78 }
79
80 /// <summary>
81 /// 显示播放状态
82 /// </summary>
83 /// <param name="sender"></param>
84 /// <param name="e"></param>
85 private void Media_State_Changed(object sender, EventArgs e)
86 {
87
88 if (_currentIndex >= 0)
89 {
90 MediaItem _currentMedia = _listMedia[_currentIndex];
91
92 switch (media.CurrentState)
93 {
94 case System.Windows.Media.MediaElementState.AcquiringLicense:
95 txtProgress.Text = "加载许可证";
96
97 break;
98 case System.Windows.Media.MediaElementState.Buffering:
99 txtProgress.Text = "缓冲中";
100 break;
101 case System.Windows.Media.MediaElementState.Closed:
102 txtProgress.Text = "已关闭";
103 break;
104 case System.Windows.Media.MediaElementState.Individualizing:
105 txtProgress.Text = "加载个性化设置";
106 break;
107 case System.Windows.Media.MediaElementState.Opening:
108 txtProgress.Text = "加载中";
109 break;
110 case System.Windows.Media.MediaElementState.Paused:
111 txtProgress.Text = "已暂停";
112 break;
113 case System.Windows.Media.MediaElementState.Playing:
114 txtProgress.Text = "正在播放";
115
116 //预选缓冲下一段视频(不过在实际测试中,感觉这么干没啥明显效果,欢迎大家共同探讨如何提前缓冲下一段视频)
117 if (_currentIndex + 1 > _listMedia.Count - 1)
118 {
119 mediaBuffer.Source = new Uri(_listMedia[0].src);
120 }
121 else
122 {
123 mediaBuffer.Source = new Uri(_listMedia[_currentIndex + 1].src);
124 }
125
126 break;
127 case System.Windows.Media.MediaElementState.Stopped:
128 txtProgress.Text = "已停止";
129 break;
130 default:
131 break;
132 }
133 }
134
135 }
136
137
138 /// <summary>
139 /// 停止播放
140 /// </summary>
141 /// <param name="sender"></param>
142 /// <param name="e"></param>
143 private void StopMedia(object sender, System.Windows.RoutedEventArgs e)
144 {
145 media.Stop();
146 btnPlay.Content = ">";
147
148 }
149
150
151
152 /// <summary>
153 /// 播放/暂停
154 /// </summary>
155 /// <param name="sender"></param>
156 /// <param name="e"></param>
157 private void PlayMedia(object sender, System.Windows.RoutedEventArgs e)
158 {
159
160 if (media.CurrentState == System.Windows.Media.MediaElementState.Paused || media.CurrentState == System.Windows.Media.MediaElementState.Stopped)
161 {
162 media.Play();
163 btnPlay.Content = "||";
164 canvas_Pause.Visibility = Visibility.Collapsed;
165
166 }
167 else
168 {
169 media.Pause();
170 btnPlay.Content = ">";
171 canvas_Pause.Visibility = Visibility.Visible;
172 }
173
174 }
175
176 /// <summary>
177 /// 一段播放完毕后,自动跳到下一段
178 /// </summary>
179 /// <param name="sender"></param>
180 /// <param name="e"></param>
181 private void media_MediaEnded(object sender, System.Windows.RoutedEventArgs e)
182 {
183 _currentIndex++;
184
185 if (_currentIndex > _listMedia.Count - 1)
186 {
187 _currentIndex = 0;
188 }
189
190 media.Source = new Uri(_listMedia[_currentIndex].src);
191
192 cboList.SelectedIndex = _currentIndex;
193 }
194
195 /// <summary>
196 /// 下拉列表改变时,播放相关片段
197 /// </summary>
198 /// <param name="sender"></param>
199 /// <param name="e"></param>
200 private void cboList_SelectionChanged(object sender, SelectionChangedEventArgs e)
201 {
202 _currentIndex = cboList.SelectedIndex;
203 if (_currentIndex > _listMedia.Count - 1)
204 {
205 _currentIndex = 0;
206 }
207
208 media.Source = new Uri(_listMedia[_currentIndex].src);
209 canvas_Pause.Visibility = System.Windows.Visibility.Collapsed;
210 media.Position = new TimeSpan(0,0,0,0,0);
211 sliderProgress.Value = 0;
212 }
213
214 /// <summary>
215 /// 暂时Canvas点击后,隐藏Canvas,同时继续播放
216 /// </summary>
217 /// <param name="sender"></param>
218 /// <param name="e"></param>
219 private void Canvas_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
220 {
221 canvas_Pause.Visibility = System.Windows.Visibility.Collapsed;
222 media.Play();
223 }
224
225 /// <summary>
226 /// 视频画面单击时,暂时播放
227 /// </summary>
228 /// <param name="sender"></param>
229 /// <param name="e"></param>
230 private void media_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
231 {
232 canvas_Pause.Visibility = System.Windows.Visibility.Visible;
233 media.Pause();
234 }
235
236 /// <summary>
237 /// 进度条拖动时,跳到相关位置
238 /// </summary>
239 /// <param name="sender"></param>
240 /// <param name="e"></param>
241 private void sliderProgress_ValueChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<double> e)
242 {
243 this.media.Position = new TimeSpan((long)(e.NewValue * 1000 * 1000 * 10));
244 }
245
246
247 //private void media_BufferingProgressChanged(object sender, RoutedEventHandler e)
248 //{
249 // txtTime.Text = "缓冲中" + media.BufferingProgress.ToString("F0") + "%";
250 //}
251
252 /// <summary>
253 /// 静音按钮的实现
254 /// </summary>
255 /// <param name="sender"></param>
256 /// <param name="e"></param>
257 private void btnVoice_Click(object sender, RoutedEventArgs e)
258 {
259 if (media.IsMuted)
260 {
261 media.IsMuted = false;
262 this.btnVoice.Content = "静";
263 sliderVoice.IsEnabled = true;
264 }
265 else
266 {
267 media.IsMuted = true;
268 this.btnVoice.Content = "音";
269 sliderVoice.IsEnabled = false;
270 }
271
272 }
273
274 /// <summary>
275 /// 调整音量大小
276 /// </summary>
277 /// <param name="sender"></param>
278 /// <param name="e"></param>
279 private void sliderVoice_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
280 {
281 if (sliderVoice == null)
282 {
283 return;
284 }
285 media.Volume = sliderVoice.Value;
286 }
287
288 private void btnFull_Click(object sender, RoutedEventArgs e)
289 {
290 Content contentObj = App.Current.Host.Content;
291 contentObj.IsFullScreen = !contentObj.IsFullScreen;
292
293
294 }
295
296
297
298 private void Content_FullScreenChanged(object sender, EventArgs e)
299 {
300 Content contentObj = App.Current.Host.Content;
301
302 if (contentObj.IsFullScreen)
303 {
304 btnFull.Content = "退";
305 }
306 else
307 {
308 btnFull.Content = "全";
309 }
310 }
311
312 /// <summary>
313 /// 显示缓冲进度
314 /// </summary>
315 /// <param name="sender"></param>
316 /// <param name="e"></param>
317 private void media_BufferingProgressChanged(object sender, RoutedEventArgs e)
318 {
319 this.txtProgress.Text = "缓冲中" + (media.BufferingProgress*100).ToString("F0") + "%";
320 canvas_Pause.Visibility = Visibility.Visible;
321 if (media.BufferingProgress >= 1.0)
322 {
323 canvas_Pause.Visibility = Visibility.Collapsed;
324 switch (media.CurrentState)
325 {
326 case System.Windows.Media.MediaElementState.Buffering:
327 txtProgress.Text = "缓冲中";
328 break;
329 case System.Windows.Media.MediaElementState.Closed:
330 txtProgress.Text = "已关闭";
331 break;
332 case System.Windows.Media.MediaElementState.Paused:
333 txtProgress.Text = "已暂停";
334 break;
335 case System.Windows.Media.MediaElementState.Playing:
336 txtProgress.Text = "正在播放";
337 break;
338 case System.Windows.Media.MediaElementState.Stopped:
339 txtProgress.Text = "已停止";
340 break;
341 default:
342 txtProgress.Text = "就绪";
343 break;
344 }
345 }
346 }
347
348 /// <summary>
349 /// 显示加载进度
350 /// </summary>
351 /// <param name="sender"></param>
352 /// <param name="e"></param>
353 private void media_DownloadProgressChanged(object sender, RoutedEventArgs e)
354 {
355 txtProgress.Text = "加载中" + (media.DownloadProgress * 100).ToString("F0") + "%";
356 if (media.DownloadProgress >= 1)
357 {
358 switch (media.CurrentState)
359 {
360 case System.Windows.Media.MediaElementState.Buffering:
361 txtProgress.Text = "缓冲中";
362 break;
363 case System.Windows.Media.MediaElementState.Closed:
364 txtProgress.Text = "已关闭";
365 break;
366 case System.Windows.Media.MediaElementState.Paused:
367 txtProgress.Text = "已暂停";
368 break;
369 case System.Windows.Media.MediaElementState.Playing:
370 txtProgress.Text = "正在播放";
371 break;
372 case System.Windows.Media.MediaElementState.Stopped:
373 txtProgress.Text = "已停止";
374 break;
375 default:
376 txtProgress.Text = "就绪";
377 break;
378 }
379 }
380 }
381
382
383
384
385 }
386
387
388 /// <summary>
389 /// 媒体元素Item自定义类
390 /// </summary>
391 public class MediaItem
392 {
393 public string src { set; get; }
394 public string name { set; get; }
395 }
396}
397
2using System.Collections.Generic;
3using System.Json;
4using System.Windows;
5using System.Windows.Controls;
6using System.Windows.Input;
7using System.Windows.Interop;
8using System.Windows.Threading;
9
10namespace Test
11{
12
13
14 public partial class MainPage : UserControl
15 {
16 private DispatcherTimer _timerPlay;
17
18 //实际应用中,以下字符串可通过wcf调用获得
19 private string _medialist = "[{src:'http://task.24city.com/video/01.mp4',name:'苹果王手机第1段'},{src:'http://task.24city.com/video/02.mp4',name:'苹果王手机第2段'},{src:'http://task.24city.com/video/03.mp4',name:'苹果王手机第3段'},{src:'http://task.24city.com/video/04.mp4',name:'蔡依林-柠檬草的味道'},{src:'http://task.24city.com/video/05.mp4',name:'我也不知道是啥'},{src:'http://task.24city.com/video/06.mp4',name:'游戏宣传片段'}]";
20
21 List<MediaItem> _listMedia = null;
22
23 int _currentIndex = -1;//正在播放的元素索引
24
25
26 public MainPage()
27 {
28 InitializeComponent();
29
30 //解析Json
31 JsonValue _jsValue = JsonArray.Parse(_medialist);
32
33 if (_jsValue.Count > 0)
34 {
35 _listMedia = new List<MediaItem>(_jsValue.Count);
36
37 for (int i = 0; i < _jsValue.Count; i++)
38 {
39 _listMedia.Add(new MediaItem() { src = _jsValue[i]["src"], name = _jsValue[i]["name"] });
40 }
41
42 _currentIndex = 0;//默认从第一个开始播放
43 media.Source = new Uri(_listMedia[_currentIndex].src);
44
45 cboList.ItemsSource = _listMedia;
46 cboList.DisplayMemberPath = "name";
47 cboList.SelectedIndex = _currentIndex;
48
49
50 this._timerPlay = new DispatcherTimer();
51 this._timerPlay.Interval = new TimeSpan(0, 0, 0, 0, 100);
52 this._timerPlay.Tick += new EventHandler(timer_Tick);
53 this._timerPlay.Start();
54 }
55
56
57 App.Current.Host.Content.FullScreenChanged += new EventHandler(Content_FullScreenChanged);
58
59
60 }
61
62 /// <summary>
63 /// timer触发时,设置进度条与播放时间同步
64 /// </summary>
65 /// <param name="sender"></param>
66 /// <param name="e"></param>
67 void timer_Tick(object sender, EventArgs e)
68 {
69 this.sliderProgress.Maximum = this.media.NaturalDuration.TimeSpan.TotalSeconds;
70
71 this.sliderProgress.ValueChanged -= new RoutedPropertyChangedEventHandler<double>(sliderProgress_ValueChanged);
72
73 this.sliderProgress.Value = this.media.Position.TotalSeconds;
74
75 this.sliderProgress.ValueChanged += new RoutedPropertyChangedEventHandler<double>(sliderProgress_ValueChanged);
76
77 this.txtTime.Text = media.Position.Hours.ToString().PadLeft(2, '0') + ":" + media.Position.Minutes.ToString().PadLeft(2, '0') + ":" + media.Position.Seconds.ToString().PadLeft(2, '0') + "/" + media.NaturalDuration.TimeSpan.Hours.ToString().PadLeft(2, '0') + ":" + media.NaturalDuration.TimeSpan.Minutes.ToString().PadLeft(2, '0') + ":" + media.NaturalDuration.TimeSpan.Seconds.ToString().PadLeft(2, '0');
78 }
79
80 /// <summary>
81 /// 显示播放状态
82 /// </summary>
83 /// <param name="sender"></param>
84 /// <param name="e"></param>
85 private void Media_State_Changed(object sender, EventArgs e)
86 {
87
88 if (_currentIndex >= 0)
89 {
90 MediaItem _currentMedia = _listMedia[_currentIndex];
91
92 switch (media.CurrentState)
93 {
94 case System.Windows.Media.MediaElementState.AcquiringLicense:
95 txtProgress.Text = "加载许可证";
96
97 break;
98 case System.Windows.Media.MediaElementState.Buffering:
99 txtProgress.Text = "缓冲中";
100 break;
101 case System.Windows.Media.MediaElementState.Closed:
102 txtProgress.Text = "已关闭";
103 break;
104 case System.Windows.Media.MediaElementState.Individualizing:
105 txtProgress.Text = "加载个性化设置";
106 break;
107 case System.Windows.Media.MediaElementState.Opening:
108 txtProgress.Text = "加载中";
109 break;
110 case System.Windows.Media.MediaElementState.Paused:
111 txtProgress.Text = "已暂停";
112 break;
113 case System.Windows.Media.MediaElementState.Playing:
114 txtProgress.Text = "正在播放";
115
116 //预选缓冲下一段视频(不过在实际测试中,感觉这么干没啥明显效果,欢迎大家共同探讨如何提前缓冲下一段视频)
117 if (_currentIndex + 1 > _listMedia.Count - 1)
118 {
119 mediaBuffer.Source = new Uri(_listMedia[0].src);
120 }
121 else
122 {
123 mediaBuffer.Source = new Uri(_listMedia[_currentIndex + 1].src);
124 }
125
126 break;
127 case System.Windows.Media.MediaElementState.Stopped:
128 txtProgress.Text = "已停止";
129 break;
130 default:
131 break;
132 }
133 }
134
135 }
136
137
138 /// <summary>
139 /// 停止播放
140 /// </summary>
141 /// <param name="sender"></param>
142 /// <param name="e"></param>
143 private void StopMedia(object sender, System.Windows.RoutedEventArgs e)
144 {
145 media.Stop();
146 btnPlay.Content = ">";
147
148 }
149
150
151
152 /// <summary>
153 /// 播放/暂停
154 /// </summary>
155 /// <param name="sender"></param>
156 /// <param name="e"></param>
157 private void PlayMedia(object sender, System.Windows.RoutedEventArgs e)
158 {
159
160 if (media.CurrentState == System.Windows.Media.MediaElementState.Paused || media.CurrentState == System.Windows.Media.MediaElementState.Stopped)
161 {
162 media.Play();
163 btnPlay.Content = "||";
164 canvas_Pause.Visibility = Visibility.Collapsed;
165
166 }
167 else
168 {
169 media.Pause();
170 btnPlay.Content = ">";
171 canvas_Pause.Visibility = Visibility.Visible;
172 }
173
174 }
175
176 /// <summary>
177 /// 一段播放完毕后,自动跳到下一段
178 /// </summary>
179 /// <param name="sender"></param>
180 /// <param name="e"></param>
181 private void media_MediaEnded(object sender, System.Windows.RoutedEventArgs e)
182 {
183 _currentIndex++;
184
185 if (_currentIndex > _listMedia.Count - 1)
186 {
187 _currentIndex = 0;
188 }
189
190 media.Source = new Uri(_listMedia[_currentIndex].src);
191
192 cboList.SelectedIndex = _currentIndex;
193 }
194
195 /// <summary>
196 /// 下拉列表改变时,播放相关片段
197 /// </summary>
198 /// <param name="sender"></param>
199 /// <param name="e"></param>
200 private void cboList_SelectionChanged(object sender, SelectionChangedEventArgs e)
201 {
202 _currentIndex = cboList.SelectedIndex;
203 if (_currentIndex > _listMedia.Count - 1)
204 {
205 _currentIndex = 0;
206 }
207
208 media.Source = new Uri(_listMedia[_currentIndex].src);
209 canvas_Pause.Visibility = System.Windows.Visibility.Collapsed;
210 media.Position = new TimeSpan(0,0,0,0,0);
211 sliderProgress.Value = 0;
212 }
213
214 /// <summary>
215 /// 暂时Canvas点击后,隐藏Canvas,同时继续播放
216 /// </summary>
217 /// <param name="sender"></param>
218 /// <param name="e"></param>
219 private void Canvas_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
220 {
221 canvas_Pause.Visibility = System.Windows.Visibility.Collapsed;
222 media.Play();
223 }
224
225 /// <summary>
226 /// 视频画面单击时,暂时播放
227 /// </summary>
228 /// <param name="sender"></param>
229 /// <param name="e"></param>
230 private void media_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
231 {
232 canvas_Pause.Visibility = System.Windows.Visibility.Visible;
233 media.Pause();
234 }
235
236 /// <summary>
237 /// 进度条拖动时,跳到相关位置
238 /// </summary>
239 /// <param name="sender"></param>
240 /// <param name="e"></param>
241 private void sliderProgress_ValueChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs<double> e)
242 {
243 this.media.Position = new TimeSpan((long)(e.NewValue * 1000 * 1000 * 10));
244 }
245
246
247 //private void media_BufferingProgressChanged(object sender, RoutedEventHandler e)
248 //{
249 // txtTime.Text = "缓冲中" + media.BufferingProgress.ToString("F0") + "%";
250 //}
251
252 /// <summary>
253 /// 静音按钮的实现
254 /// </summary>
255 /// <param name="sender"></param>
256 /// <param name="e"></param>
257 private void btnVoice_Click(object sender, RoutedEventArgs e)
258 {
259 if (media.IsMuted)
260 {
261 media.IsMuted = false;
262 this.btnVoice.Content = "静";
263 sliderVoice.IsEnabled = true;
264 }
265 else
266 {
267 media.IsMuted = true;
268 this.btnVoice.Content = "音";
269 sliderVoice.IsEnabled = false;
270 }
271
272 }
273
274 /// <summary>
275 /// 调整音量大小
276 /// </summary>
277 /// <param name="sender"></param>
278 /// <param name="e"></param>
279 private void sliderVoice_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
280 {
281 if (sliderVoice == null)
282 {
283 return;
284 }
285 media.Volume = sliderVoice.Value;
286 }
287
288 private void btnFull_Click(object sender, RoutedEventArgs e)
289 {
290 Content contentObj = App.Current.Host.Content;
291 contentObj.IsFullScreen = !contentObj.IsFullScreen;
292
293
294 }
295
296
297
298 private void Content_FullScreenChanged(object sender, EventArgs e)
299 {
300 Content contentObj = App.Current.Host.Content;
301
302 if (contentObj.IsFullScreen)
303 {
304 btnFull.Content = "退";
305 }
306 else
307 {
308 btnFull.Content = "全";
309 }
310 }
311
312 /// <summary>
313 /// 显示缓冲进度
314 /// </summary>
315 /// <param name="sender"></param>
316 /// <param name="e"></param>
317 private void media_BufferingProgressChanged(object sender, RoutedEventArgs e)
318 {
319 this.txtProgress.Text = "缓冲中" + (media.BufferingProgress*100).ToString("F0") + "%";
320 canvas_Pause.Visibility = Visibility.Visible;
321 if (media.BufferingProgress >= 1.0)
322 {
323 canvas_Pause.Visibility = Visibility.Collapsed;
324 switch (media.CurrentState)
325 {
326 case System.Windows.Media.MediaElementState.Buffering:
327 txtProgress.Text = "缓冲中";
328 break;
329 case System.Windows.Media.MediaElementState.Closed:
330 txtProgress.Text = "已关闭";
331 break;
332 case System.Windows.Media.MediaElementState.Paused:
333 txtProgress.Text = "已暂停";
334 break;
335 case System.Windows.Media.MediaElementState.Playing:
336 txtProgress.Text = "正在播放";
337 break;
338 case System.Windows.Media.MediaElementState.Stopped:
339 txtProgress.Text = "已停止";
340 break;
341 default:
342 txtProgress.Text = "就绪";
343 break;
344 }
345 }
346 }
347
348 /// <summary>
349 /// 显示加载进度
350 /// </summary>
351 /// <param name="sender"></param>
352 /// <param name="e"></param>
353 private void media_DownloadProgressChanged(object sender, RoutedEventArgs e)
354 {
355 txtProgress.Text = "加载中" + (media.DownloadProgress * 100).ToString("F0") + "%";
356 if (media.DownloadProgress >= 1)
357 {
358 switch (media.CurrentState)
359 {
360 case System.Windows.Media.MediaElementState.Buffering:
361 txtProgress.Text = "缓冲中";
362 break;
363 case System.Windows.Media.MediaElementState.Closed:
364 txtProgress.Text = "已关闭";
365 break;
366 case System.Windows.Media.MediaElementState.Paused:
367 txtProgress.Text = "已暂停";
368 break;
369 case System.Windows.Media.MediaElementState.Playing:
370 txtProgress.Text = "正在播放";
371 break;
372 case System.Windows.Media.MediaElementState.Stopped:
373 txtProgress.Text = "已停止";
374 break;
375 default:
376 txtProgress.Text = "就绪";
377 break;
378 }
379 }
380 }
381
382
383
384
385 }
386
387
388 /// <summary>
389 /// 媒体元素Item自定义类
390 /// </summary>
391 public class MediaItem
392 {
393 public string src { set; get; }
394 public string name { set; get; }
395 }
396}
397
作者:菩提树下的杨过
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://yjmyzz.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。