PPMM频道列表设计及实现
(任何引用请注明:转载于美人山下http://www.beautyhill.blogspot.com)
    PPMM的频道列表是一个逻辑不难、但实现较烦的程序部分。笔者一直以来的想法是,拥有一个频道多级、交叉分类的列表形式。比如说,影片《兄弟连》在列表上位置应该是这些:1,类型/电影/欧美/战争/《兄弟连》;2,产地/欧美/电影/战争/《兄弟连》;3,主题/战争/欧美/电影/《兄弟连》……
    读者一定发现了,这种分类多种多样,过于自由甚至没有一定的规律可寻了,因此笔者在感觉想法不成熟的情况下,对目标进行了简化:根目录分《官方分类》、《自制分类》、《我的收藏》三级;《官方分类》目录下,延续官方的两级分类;《自制分类》则将官方分类进行自定义命名,然后重新归类;《我的收藏》则保存了心爱节目的链接,方便查找以在第一时间播放。
    这种组织结构必然带来了一个问题:播放事件的处理。当用户要求播放的时候,如何判断用户选择的当前TreeView节点是有效的节目源,这是我心中挥之不去的疙瘩。从一开始的判断是否叶节点,到后来判断节点的name是否在节目列表内,却始终未让我满意。参见如下代码:
private void tvList_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) {
try {
Channel channel = (Channel)Channel.ChannelsSearch[e.Node.Name];
if (channel != null) {
if (this.hasLogin)
this.Send(Protocol.SplitTag.ToString() + (int)(Protocol.ClientCommand.RoomChannel)
+ Protocol.SplitTag.ToString() + e.Node.Name);
else
this.Play(e.Node.Name);
}
}
catch (Exception E) {
this.rtbMessageAppendText("\n频道播放失败!\n" + E.Message);
}
}
    实际说来,这个列表的实现,难点可能在于所有节目的加载;即如何从网络上得到这么多的节目,如何将不同厂商(PPLive、PPStream等)的节目进行综合,又如何对不同厂商的节目进行播放处理。有关网络节目源获取的内容,请参见网络视频频道源RSS(XML)文件读取。下文中,我将告诉读者我是如何处理不同厂商节目源的播放问题的。
    在节目的抽象上,我将他设计成一个Channel类,带有Manufacture,Name,Catalog,Url等字段或属性,同时拥有loadChannels()等静态方法,用以自动加载网络频道。在频道进行初始化后(调用静态方法init()),各类信息将储存在Channel类中,其他实体通过Channel的静态方法读取某个频道,而通过该频道的各个字段,了解频道的细节,继而分析事件。
    举频道播放一例而言,当用户要求播放某个频道时,通过频道的Manufacture(厂商)字段,然后选择合适的播放器进行播放。代码如下:
public void Play(string channelID) {
try {
Channel channel = (Channel)Channel.ChannelsSearch[channelID];
if (channel == null) {
this.tcViews.SelectedIndex = 0;
this.pplivePlayer.Stop();
this.ppstreamPlayer.Stop();
this.mediaPlayer.URL = channelID;
}
else {
this.lvChannelDetails.Items.Clear();
string[] s = { "频道", channel.Name };
this.lvChannelDetails.Items.Add(new System.Windows.Forms.ListViewItem(s));
string[] s0 = { "厂商", channel.Manufacture };
this.lvChannelDetails.Items.Add(new System.Windows.Forms.ListViewItem(s0));
string[] s1 = { "作者", channel.Author };
this.lvChannelDetails.Items.Add(new System.Windows.Forms.ListViewItem(s1));
if (channel.Manufacture.Equals("PPLive")) {
this.tcViews.SelectedIndex = 1;
this.mediaPlayer.URL = "";
this.ppstreamPlayer.Stop();
this.pplivePlayer.URL = channel.Link;
this.pplivePlayer.Play();
this.ssMain.Items[0].Text = "正在链接频道 - " + channel.Name + " ......";
}
else if (channel.Manufacture.Equals("PPStream")) {
this.tcViews.SelectedIndex = 2;
this.mediaPlayer.URL = "";
this.pplivePlayer.Stop();
this.ssMain.Items[0].Text = "正在读取链接 - " + channel.Name;
this.ppstreamPlayer.src = Channel.GetPPStreamChannelUrl(channel.Link);
this.ppstreamPlayer.Play();
this.ssMain.Items[0].Text = "正在链接频道 - " + channel.Name + " ......";
}
else
this.rtbMessageAppendText("\n指定的播放厂商无效!");
}
}
catch (Exception E) {
this.rtbMessageAppendText("\n频道播放失败!\n" + E.Message);
}
}
    当前网络视频市场尚等待重新洗牌,因此厂商驳杂,规范不一;在江湖事起的年代,我们这些小人物只能耐住性子,逐一分析各厂商的协议规范,通过绕各种弯路,以达到“一统天下”的目的;虽然这是表面上的虚假繁荣(技术可达),却也有点实用。
    在PPMM的项目中,我只收集了PPLive和PPStream两个厂商的节目源,但二者对节目的属性定义各异,笔者只能折中,考虑到维护难度,简化了频道的字段;但即便如此,对PPStream节目Url的抓取,还是让程序颇费了一番周折,因此,用户播放PPStream节目的时候可能有严重的延迟现象。


没有评论:
发表评论