openMeetings二次开发高手的七篇文章.docx
《openMeetings二次开发高手的七篇文章.docx》由会员分享,可在线阅读,更多相关《openMeetings二次开发高手的七篇文章.docx(37页珍藏版)》请在冰豆网上搜索。
openMeetings二次开发高手的七篇文章
第一章PhMeetings——基于OpenMeetings的实验性商业版本
OpenMeetings2010-09-2916:
42:
53阅读279评论0 字号:
大中小 订阅
作者:
老猫
PhMeetings是基于开源WEB视频会议系统OpenMeetings开发的一个实验性商业版本,原始蓝本来自OpenMeetings1.2。
老猫花了好几个月的时间,费了九牛二虎之力至今天终于完成了一个目前还算过得去的版本,沾沾自喜中……
由于资料的缺乏以及对OpenLaszlo编程的陌生,其中艰辛不足为外人道。
今日发一声感慨:
如果你想折磨一个程序员,那就让他去干开源软件的二次开发!
好了,言归正传,先推销一下PhMeetings的演示地址:
http:
//117.135.134.66:
5080/phmeetings
参考国内流行的一些C/S架构下的网络视频会议系统,老猫的PhMeetings在OpenMeetings基础上增加了一些适合独立进行商业运营的概念和功能,同时也删减了一些不符合国内网络环境或者形同鸡肋的功能。
删除的功能有:
● SIP接入网关(IPphone在国内基本用不上)
● 预约会议功能(这个在商业运营商很难掌控)
● 屏幕共享功能(除非部署在局域网环境,否则会把人急死)
● 取消了其它类型房间的录制功能,只保留interview类型房间内的录制功能
新增的概念或功能:
● 房间目录树概念:
用于对房间采用树状目录管理
● 新增用户类型:
房主。
使得房间的租用概念得以商业化推广。
● 房间计费管理及租用到期提醒功能
● 新增房间管理后台功能:
房主可以管理房间超级主持人、LOGO、背景、黑名单、白名单、链接及广告等。
● 房间收藏和房间搜索功能:
方便在众多的房间中找到你想要去的。
● 房间锁功能:
可对房间设置进入密码。
● 踢出房间功能:
超级管理员或者房主有权在房间里将捣乱的用户踢出系统。
● 黑名单功能:
将用户ID或者IP加入房间黑名单,该用户将被该房间拒之门外。
● 白名单功能:
列入房间白名单的用户在房间设置密码锁时可以不必输入密码验证。
● 游客直接通过链接进入房间功能:
房间租用者可以对游客开展产品推介或其它客服服务。
● 房间内显示背景、LOGO、广告及链接功能
● 房间欢迎语滚动显示
● 增加了全屏显示功能(可惜全屏时聊天的输入无法使用)
● 增加了视频配置里的视频帧数调节
改进的部分有:
● 对界面进行美化和改进
● 修正了移植数据库到ORACLE时的一些BUG
● 改进了房间的整体布局
● 对中文化不彻底的地方进行了完善
● 改进了视频的显示和布局方式
● 改进了摄像头采集区域的一些BUG
● 优化了音频和视频参数配置
● 增加用户默认头像的性别区分
● 将用户信息从firstname、lastname等西方习惯改为昵称
欢迎有兴趣的朋友注册PhMeetings参与体验。
或者以游客身份直接进入OpenMeetings技术群专属房间参与讨论。
第二章OpenMeetings二次开发实例
(一)游客直接进入房间
OpenMeetings2010-09-2910:
42:
15阅读474评论1 字号:
大中小 订阅
作者:
老猫
决定写点东西,技术细节上的东西在二次开发过程中可以慢慢摸索和体会,如果要把这些改造过程中的细节都记录下来,对我这个懒人来说比较困难。
作为IT行业的一个老兵,现在的兴趣已无法集中具体的代码上了,吸引我的更多的是如何设计一个系统,使它的性能和功能能符合某个领域的需求。
研究OpenMeetings已经几个月了,当初对这个项目感兴趣是因为这个项目是一个基于WEB的应用。
而目前绝大部分投入实用阶段的视频会议系统都是基于C/S架构的,从CISCO的基于硬件的专业化视频会议系统,到新浪UC、9158等开放的视频聊天或KTV系统,都必须安装客户端甚至专用硬件。
而OpenMeetings的特点是它把前台构筑在Flash的基础上(客户端被编译成了一个swf文件),如此,只要客户的机器的浏览器安装了FlashPlayer插件,就可以毫无障碍地运行起来。
碍于Flash对于webcam的视频和音频的实时采样压缩和传输的能力,目前在性能上,OpenMeetings还无法与C/S架构的视频会议系统相比。
但OpenMeetings的先天优势在于它的完全B/S架构,使得它可以无缝地与网站相衔接。
我们设想一些网络应用,比如企业的产品推广或者网上店铺的商品展示,它们的目标对象大部分不是固定的,而是随机的游客。
采用传统的视频会议系统,需要下载安装客户端并且注册登录等一堆操作,对于只是路过的游客来说,99%是不可能做这些的。
假如我们只需要一个链接填写一个昵称就能进入到一个视频会议房间,该房间里有值班的客服,随时可以为你通过视频、白板等推介商品,那么至少有一半以上的游客是乐意这么做的。
我们设想的这个商业应用,很关键的一个环节是不需要注册和登录等等环节,也不需要用户熟悉这个系统或者去搜索某个房间的入口,而是通过网站上的某个链接地址点击直接进入指定的房间。
比如某个网购门户,每个商家都在OpenMeetings拥有一个产品推介房间,那么它的店铺内就显示一个直通该房间的链接,游客点击该链接,系统要求用户输入一个昵称后就直接将用户重定向到该房间内由房间值班员和用户进行视频互动。
OK,我们就把这个应用当作一个方向来改进和设计OpenMeetings。
那么今天的这篇文章,就来讲述一下如何在OpenMeetings上实现一个游客直通房间的功能。
首先,我们设计一个类,这个类用户实现游客的登录名的自动生成。
系统接受游客时需要自动为游客生成一个登录名(loginname),我们可以把它涉及成guestXXXXXX的形式,XXXXXX的号码是从0~999999之间顺序生成的。
publicclassGuestNumManagement{
privatestaticGuestNumManagementinstance=null;
privatelongcurrentNum=0;
privateGuestNumManagement(){
}
publicstaticsynchronizedGuestNumManagementgetInstance(){
if(instance==null){
instance=newGuestNumManagement();
}
returninstance;
}
publiclongnextNum(){
if(currentNum>999999){
resetNum();
}
longn=currentNum++;
returnn;
}
publicvoidresetNum(){
currentNum=0;
}
}
接下来,我们仿照OpenMeetings的SOAP接口来实现一个servlet,这个servlet接收房间号、游客的昵称和性别,然后调用SOAP接口组装成一个直接进入房间的url,并且将用户浏览器重定向到这个url。
publicclassDirectGatewayextendsHttpServlet{
privatestaticfinalLoggerlog=Red5LoggerFactory.getLogger(DirectGateway.class,"phmeetings");
protectedvoidservice(HttpServletRequesthttpServletRequest,
HttpServletResponsehttpServletResponse)throwsServletException,
IOException{
httpServletRequest.setCharacterEncoding("utf-8");
httpServletResponse.setContentType("text/html;charset=utf-8");
httpServletResponse.setCharacterEncoding("utf-8");
try{
//获得房间ID
Stringroomid=httpServletRequest.getParameter("roomid");
if(roomid==null){
PrintWriterout=httpServletResponse.getWriter();
out.println("未获得roomid,请检查参数!
");
out.flush();
out.close();
return;
}
if(roomid.equals("")){
PrintWriterout=httpServletResponse.getWriter();
out.println("房间ID不能为空且必须是一个整数!
");
out.flush();
out.close();
}
Longroom_id=null;
try{
room_id=Long.parseLong(roomid);
}
catch(Exceptione){
PrintWriterout=httpServletResponse.getWriter();
out.println("房间ID必须是一个数值!
");
out.flush();
out.close();
return;
}
//检查是否有该房间
Roomsroom=Roommanagement.getInstance().getRoomById(room_id);
if(room==null){
PrintWriterout=httpServletResponse.getWriter();
out.println("指定的房间不存在或已被删除!
");
out.flush();
out.close();
return;
}
//获得昵称
Stringnickname=null;
Integersex=newInteger(0);
try{
nickname=httpServletRequest.getParameter("nickname");
StringsSex=httpServletRequest.getParameter("sex");
if(sSex==null||sSex.equals("")){
sex=null;
}else{
sex=Integer.parseInt(sSex);
}
}
catch(Exceptione){
//...
}
//生成用户名,格式为guestXXXXXX
Stringusername=null;
//获得新序号
longnum=GuestNumManagement.getInstance().nextNum();
username="guest"+Long.toString(num)+"~"; //~符号表示为游客
//第一步,获得session
SessiondatasessionData=MainService.getInstance().getsessiondata();
StringsessionId=sessionData.getSession_id();
//第二步,登录用户
Usersuser=room.getUser();
//扩展登录方法,使得直接用MD5比对
Objectobj=Usermanagement.getInstance().loginUserEx(sessionId,user.getLogin(),null,false,null);
LongreturnVal=newLong(-1);
if(obj==null){
returnVal= newLong(-1);
}
StringobjName=obj.getClass().getName();
if(objName.equals("java.lang.Long")){
returnVal=(Long)obj;
}else{
returnVal=newLong
(1);
}
if(returnVal!
=1){
PrintWriterout=httpServletResponse.getWriter();
out.println("房主授权验证失败!
");
out.flush();
out.close();
return;
}
//第三步,获得Hash
Longusers_id=Sessionmanagement.getInstance().checkSession(sessionId);
Longuser_level=Usermanagement.getInstance().getUserLevelByID(users_id);
returnVal=newLong(0);
//验证房间人数
if(room.getCurrentusers()!
=null){
if(room.getCurrentusers().size()>=room.getNumberOfPartizipants()){
//房间已满
returnVal=newLong(-1001);
}
}
//其它验证:
是否加锁、IP地址是否列入黑名单
//...
if(returnVal==0){
//更新session里的数据
RemoteSessionObjectremoteSessionObject=newRemoteSessionObject(username,nickname,sex,
"","",null,"");
XStreamxStream=newXStream(newDomDriver("UTF-8"));
xStream.setMode(XStream.NO_REFERENCES);
StringxmlString=xStream.toXML(remoteSessionObject);
log.debug("xmlString"+xmlString); Sessionmanagement.getInstance().updateUserRemoteSession(sessionId,xmlString);
Stringhash=SOAPLoginDAO.getInstance().addSOAPLogin(sessionId,room_id,
false,false,false,null);
if(hash!
=null){
//重定向
Stringwebroot=ScopeApplicationAdapter.webAppRootKey;
//调试使用
//httpServletResponse.sendRedirect("/"+webroot+"/maindebug.lzx?
secureHash="+hash+"&lzproxied=solo&lzr=swf8");
//正式
httpServletResponse.sendRedirect("/"+webroot+"/main.swf8.swf?
secureHash="+hash+"&lzproxied=solo");
}
else{
returnVal=newLong(-1);
}
}
if(returnVal!
=0){
PrintWriterout=httpServletResponse.getWriter();
if(returnVal==-1001){
out.println("房间已满,请稍后再试!
");
}
else{
out.println("未知错误!
");
}
out.flush();
out.close();
return;
}
}catch(Exceptioner){
log.error("ERROR",er);
System.out.println("Errorexporting:
"+er);
er.printStackTrace();
}
}
}
需要提一下的是,上述代码中,在第二步时,我使用了一个loginUserEx的方法,这个方法是我自己的扩展的,目的是把从原有的基于管理员的用户验证改成基于房主的身份验证。
room.getUser()方法也是扩展的,即获得房间的房主用户,然后使用loginUserEx来验证。
读者可以仍然使用loginUser的方法来代替loginUserEx,但这里必须使用管理员的登录名和密码。
接下来,我们再来设计一个输入用