作者:董维春
CSDN专栏作家(ch_builder),CB论坛ActiveX\COM\DCOM栏目斑主,有多篇文章发表在《程序员》杂志上。
BLOG:http://blog.csdn.net/ch_builder
研究方向:小型数据库开发、报表开发、Office办公系统应用
邮箱:ch_builder@163.com
QQ:116001522
注:本文已发表在《编程技巧与维护》2005年第一期中,应广大朋友的要求,发表于此!
你若想转载或摘抄,可与作者联系,谢谢!
用CB编写网络电视
作者:董维春
在网上收看电视、收听广播,其实并不是一件很难的事情,网上的视频或音频流多数是用Windows Media Player、RealPlayer,两者所占比例差不多。但这些节目也不是分布在一起的,要是一个一个的去找也不太方便,而随着在线流媒体数量的增多,各种版本的网络电视如雨后春笋,他们多数要注册,让不就是广告一堆。女朋友闹着也要拥有一个属于自己的类似软件,我就动手做了一个,觉得还不错,对于是否写出源码的分析,我也想过好久。其实写出来并不难,但人可能就是这样,当掌握了一点书本上根本就没有的东西或自己的心血就要成为别人的时候难免有些不安。这可能也是我们中国软件业的一个最大问题,人们总是很少交流,总让别人公开源码,而自己呢?那日与欧阳璄老弟说到此事时,他的想法与我惊人的相似,为什么不公开让大家互相学习,在学习和总结中共同前进呢?于是有了此文。
为了便于说明,先把程序中的两个窗体给出(还有一个关于窗体,这里就不给出了),当我们选择收音时,视频窗口是不会出现的,只有播放电视时才会出现J
(图1,控制面板frmContronl)
(图2,视频窗口frmWindow)
一、TTWindowsMediaPlayer与TRealAudio组件的基础知识
这个程序的核心中是对TWindowsMediaPlayer与TRealAudio这两个ActiveX组件的应用。我们有必要先了解一下这两个组件。
先看一下在你的ActiveX页中(当然也可能在你自定义的其它组件页中,系统默认的通常是ActiveX页)有没有TWindowsMediaPlayer与TRealAudio这两个ActiveX组件,如果没有,那你要自行安装。关于一些这方面的一些基础知识可参见我写的《在BCB中轻松使用ActiveX控件》,网址:
http://www.csdn.net/develop/Read_Article.asp?Id=19032
相信你看过后会对这个两个组件有所了解。这里我们再介绍一些程序中能用到的、鲜为人知的属性及方法。
1)TWindowsMediaPlayer组件的属性及方法:
TWindowsmediaplayer中的一些特殊属性我们可以调用Windows Media Player属性框来完成。只要我们双击TWindowsmediaplayer这个组件,就会弹出Windows Media Player属性框。若我们只想要一个显示窗口,那只在常规的控件布局中我们选择None,就可以了。选择自动起动时,只要给出URL,TWindowsmediaplayer就可以自动开始播放了。
这个对话框可以实现很多功能,我们一定应该花些时间熟悉她,这并不太难,只要用几次就应该差不多了。
URL属性:文件名或网上链接地址;
Status属性:状态栏信息;
Close():关闭正在播放的内容。
TWindowsmediaplayer状态表:
|
OpenState属性值
|
PlayState属性值
|
WMP当时状态
|
|
12
|
9
|
准备开始
|
|
10
|
9
|
正在连接
|
|
13
|
6
|
正在缓冲
|
|
13
|
3
|
正在播放
|
|
13
|
6
|
准备就绪(播放失败)
|
|
13
|
1
|
停止播放
|
2)TRealAudio组件属性及方法:
Controls属性:IMAGEWINDOW,CONTROLPANEL,STATUSBAR(其中:IMAGEWINDOW、CONTROLPANEL、STATUSBAR分别表示显示视频播放窗口、控制条、状态条),在这个程序中我们只给出IMAGEWINDOW一个值,也就是我们只得到视频窗口;
Source属性:文件名或网上链接地址;
DoPlay():播放;
DoStop():停止播放;
GetLastMessage():建立连接的信息;
GetBandWidthAverage():当前播放的平均速率,单位比特/秒;
GetPlayState()属性值含义:
|
GetPlayState()属性值
|
TRealAudio当时状态
|
|
0
|
停止
|
|
1
|
正在连接
|
|
2
|
正在缓冲
|
|
3
|
正在播出
|
|
4
|
暂停
|
二、程序的初步实现
1)从数据库中得到相关信息
程序的实现并不困难,首先从数据库中取得要播放的电视(或广播)的相关的信息,很显示我们要从库中得到足够的数据才能更有利我们下面的程序的设计。由于流媒体的格式不同,我们有必要在我们的库中写出一个流媒体格式的字段,这样更有利用程序判断是到底应该选用那个组件。同样,对于视频窗口,我们没有必要在听广播时或无播放时放在桌面上,只有在播放视频时才调用这来,至于什么时候调用我们也完全在数据库中给出是否调用视频窗口这个字段。当然在数据库中一些最基本的字段,如电视台或广播台的基本信息与流地址是必须给出的。当然这些内容都是从库中提取出来的,下面是有关数据库提取的代码:
void __fastcall TfrmControl::sbnNextClick(TObject *Sender)
{
if(sbnTV->Down==true||sbnRD->Down==true)//判断数据库是否连接,原程序中我用了两个数据联接组件,且 sbnTV与sbnRD是选择那一个连接的按钮,它们均是位图按钮,这里充分利用了他们的Down属性,至于联接程序你可以视具体情况自行编写,其中sbnTV控制电视节目的连接,sbnRD控制广播节目的连接
{
if(sbnTV->Down==true)//确定qryTV是否连接
{
if(qryTV->Eof!=true)//因为向下选,防止到最后一个还向后选
{
qryTV->Next();//选择下一条记录
}
else
{
qryTV->First();//回到第一条记录
}
//从数据库中取出相关数据,此处所用的变量均为全局变量,String型
lblPlaying->Caption=qryTV->FieldValues["Name"];//所选节目名称
chname=qryTV->FieldValues["Name"];//所选节目名称
chtype=qryTV->FieldValues["Type"];//所选节目,所用的播放格式
chaddress=qryTV->FieldValues["Address"];//所选节目的流地址
}
else
{
if(qryRD->Eof!=true)
{
qryRD->Next();
}
else
{
qryRD->First();
}
lblPlaying->Caption=qryRD->FieldValues["Name"];
chname=qryRD->FieldValues["Name"];
chtype=qryRD->FieldValues["Type"];
chaddress=qryRD->FieldValues["Address"];
}
sbnNext->Down=false;
}
else//若数据库没连接,则提示连接
{
ShowMessage("请先选择右侧的电视或收音键");
}
}
//---------------------------------------------------------------------------
2)播放功能的实现
TWindowsMediaPlayer与TRealAudio两个组件是应用是这个程序的核心部分,播放功能的实现就是充分利用他们的结果。这两个组件都放在视频窗口中,如图2,黑色的框体就是他们了,当然他们是完全重合在一起的,我想这并不难,而关于他们的基本设计前面已经说过,这里重点在代码的实现上:
void __fastcall TfrmControl::sbnPlayClick(TObject *Sender)
{
if(chtype=="rtsp")//判断播放格式
{
//若类型为rtsp,则调用realplayer播放器,mediaplayer则关闭、隐藏
frmWindow->wmpChtv->close();
frmWindow->wmpChtv->Hide();
frmWindow->raChtv->Show();//启用RealAudio
frmWindow->raChtv->Source=chaddress;//给定流地址
frmWindow->raChtv->DoPlay();//播放
lblStatus->Caption=frmWindow->raChtv->GetLastMessage();//获取连接信息
if(frmWindow->raChtv->GetPlayState()==3)//如果正在播放,则显示播放速率
{
lblStatus->Caption="当前播放为"+frmWindow->raChtv->GetBandwidthAverage()+"比特/秒";
}
lblPlay->Caption=lblPlaying->Caption;//在面板中显示播放的节目名
ra=true;//指出这里选用的是realplayer播放器,ra是全局变量,bool型,这里的目的是告知停止时知道当前播放的格式,采取相应的停止收段
}
else
{
frmWindow->raChtv->DoStop();//停止realplayer播放
frmWindow->raChtv->Hide();//把realplayer隐藏
frmWindow->wmpChtv->Show();//调用mediaplayer
frmWindow->wmpChtv->URL=chaddress;//给出流地址
lblPlay->Caption=lblPlaying->Caption;
ra=false;//指出这里选用的不是realplayer播放器
}
if(sbnTV->Down==true)//判断是否调出视窗窗体
{
frmWindow->Show();
}
else