Naive Media Player

简单实现了一个Naive Media Player两次。
为什么是两次呢,因为在第一次写完同步到github上时,手抖删除了对分支的更改。怒删重写后被dalao告知可以恢复呀QAQ。
得到惨痛教训珍爱生命,远离手抖;珍爱生命,学好git。重写完后觉得第二次画的背景图更interesting,就换了几张截图,故几张图细节可能有变动。
打开首页如下
open
可点击右上角选择打开文件
openfiles
播放视频效果如下
video
播放音频效果如下,会直接显示背景
audio
以下是在实现过程中考虑到的和遇到的问题

播放视频、音频

首先想到的问题就是如何播放视频和音频。刚开始参考了XAML Controls Gallery,其中的介绍 和演示都非常简单。我尝试使用以下代码却发现并不能播放视频。

1
2
3
4
5
<MediaPlayerElement Source="/Assets/test.mp4"
MaxWidth="400"
AutoPlay="False"
AreTransportControlsEnabled="True" />
}

VS会报出两个错误,一个是当前平台支持的最低版本不支持 MediaPlayerElement,二是Convert不能直接将String转换为Source。第一个问题可以通过修改 调试-属性-应用程序 中修改最低版本来解决。
第二个问题大概意思就是不能通过String类型的文件路径转换为Source了类型的。所以我又参考了MS官方文档中Play a media file with MediaPlayer
Use MediaPlayerElement to render video in XAML
大概理解了如何使用这两个控件。即在XAML中放置控件MediaPlayerElement,但不在XAML中设置该控件的source之类的属性,只设置与界面有关的;在.cs文件中声明 MediaPlayer,并在.cs中设置其source,然后将XAML中的PlayerElement的播放器绑定为.cs中的MediaPlayer。
的确这样写更好,在XAML文件中设置布局与控件,在.cs中写逻辑。代码如下:

1
2
3
4
5
6
7
<MediaPlayerElement x:Name="mediaSimple"
AutoPlay="False"
AreTransportControlsEnabled="True"
IsEnabled="True"
Grid.Row="1"
/>
}

1
2
3
MediaPlayer myPlayer = new MediaPlayer();
myPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/test.mp4"));
mediaSimple.setMediaPlayer(myPlayer);

然而仍然无法播放QAQ!在小方的帮助下,解决了这个问题。因为用的test.mp4文件放在了Assets文件夹下但是并没有在VS中吧该文件添加到项目里。在解决方案资源管理器中右键-添加-已有项目,选择test.mp4。

选择文件

选择文件按钮

界面需要一个按钮来选择文件,这里选择了在第一行添加CommandBar,CommandBar的content来显示打开的文件名,AppButton来选择要打开的文件。参考了文档Command Bar

1
2
3
4
5
6
<CommandBar DefaultLabelPosition="Right" IsOpen="False" Grid.Row="0">
<CommandBar.Content>
<TextBlock Name="Title" FontSize="24" Margin="12,14"/>
</CommandBar.Content>
<AppBarButton Icon="OpenFile" Label="openFile" Click="AppBarButton_Click" />
</CommandBar>

但是发现有一个问题就是在CommandBar的右边总是显示[···]的More 按钮,于是又看了一下文档,发现CommandBar有OverflowButtonVisibility属性,
修改为隐藏即可。

1
<CommandBar DefaultLabelPosition="Right" IsOpen="False" OverflowButtonVisibility="Collapsed" Grid.Row="0">

选择本地文件

仍然参考官方文档Open files and folders with a picker写出如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private void AppBarButton_Click(object sender, RoutedEventArgs e)
{
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
picker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
picker.FileTypeFilter.Add(".mp3");
picker.FileTypeFilter.Add(".mp4");
Windows.Storage.StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
// Application now has read/write access to the picked file
this.textBlock.Text = "Picked photo: " + file.Name;
}
else
{
this.textBlock.Text = "Operation cancelled.";
}
}

然而多处报错,在根据VS的提示修改之后,错误更加严重了,AppBarButton_Click方法返回值类型不匹配。于是又借助搜索引擎,找到一篇blog参考它写出如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private async void add_Click(object sender, RoutedEventArgs e)
{
var openPicker = new FileOpenPicker();
openPicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.VideosLibrary;
openPicker.FileTypeFilter.Add(".mp4");
openPicker.FileTypeFilter.Add(".mp3");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
var mediaSource = MediaSource.CreateFromStorageFile(file);
Title.Text = file.Name;
myPlayer.Source = mediaSource;
mediaSimple.SetMediaPlayer(myPlayer);
if (file.FileType == ".mp3")
{
//Todo 播放音频时显示专辑封面旋转
//可通过 Ellipse 实现
}
}
}

乍看没什么区别,为什么第一次就报错呢?仔细对比发现,第一次的代码在根据VS提示自动修改后会变成:

1
private async System.Threading.Tasks.Task AppBarButton_ClickAsync(object sender, RoutedEventArgs e)

将返回值类型修改成了task,这也就是为什么报错是返回值类型不匹配。这里其实之前嗨翻了一个错误,就是没有写 mediaSimple.setMediaPlayer(myPlayer);这句,导致打开文件之后一直啥也没有。
通过 myPlayer.play(); 测试出已经正常打开文件了,这才找出是因为没有和XAML的控件绑定导致的。

界面

打开应用和播放音频时直接显示白色界面,看起来有些简陋。参考blog
给Grid添加Image来简单装饰,于是打开画图板绘制了一张切合标题的背景图。

1
2
3
<Grid.Background>
<ImageBrush ImageSource="Assets/pic.png" Opacity="0.9" />
</Grid.Background>

总结

出现问题时要认真看报错啊,FileOpenPicker那个错误报错已经很明显了。
官方文档才是最全面最可靠的。
最后希望写代码的时候能头脑清醒,少犯智障的错误,尤其是写完了却误删代码这种,可长点心吧。