当我第一次发现ice:outputMedia tag的时候,我对它赞不绝口。的确,只要使用了这个tag,就可以轻松的在网页中使用flash player,media player,real play和quick time。然后,我就将它运用到我的网站中播放音频文件,很快,不足就暴露出来:
1)没有提供控制命令,比如停止播放,开始播放等。
2)当配制成使用flash的时候,不能播放mp3文件,只能播放swf文件。
3)无法知道音频文件什么时候播放完成,这在网站中连续播放文件时非常必要。
4)当然,ice:outputMedia有一个很好的优点,就是当我更新它的source属性值为其他音频文件路径时,它就会开始播放其他文件。可是,这也带来了第四个缺点,在IE下,如果旧文件还没有播放完毕,那么它仍会继续播放,用户会听到新旧两个文件在同时播放。
ice:outputMedia目前功能还很初级,要扩展它,必须首先了解它生成的代码。让我们先来生成一个测试工程T1,基于NetBeans6.7.1的ICEFaces1.8.1和facelets。创建顺序请看下面截图:
现在,我们先来测试ice:outputMedia对media player的支持。在welcomeICEfaces.xhtml文件中添加如下代码:
然后,我们利用向导创建一个TestBean类,并拥有属性soudFilePath。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* @author Administrator
*/
public class TestBean {
/** Creates a new instance of TestBean */
public TestBean() {
}
private String soundFilePath;
/**
* @return the soundFilePath
*/
public String getSoundFilePath() {
return soundFilePath;
}
/**
* @param soundFilePath the soundFilePath to set
*/
public void setSoundFilePath(String soundFilePath) {
this.soundFilePath = soundFilePath;
}
}
现在,准备一首mp3歌曲文件,命名为1.mp3,放到netbeans工程的build/web目录下。设置soundFilePath的初始值为1.mp3。由于浏览器的行为有些差异,我们先使用FireFox3.5来检查(在NetBeans中可以设置采用哪一种浏览器)。运行效果如下:
注意,可能你的windows上的FireFox3.5不能播放,你需要安装一个插件MediaWrap。下面,来观察一下ice:outputMedia生成的代码。由于NetBeans6.7.1的javascript调试器对于我们的工程无效,所以先要在Firefox上安装firebug插件。装好后,Firefox右下角会有一个虫子形状的图标,点击它,将出现下面的窗口:
仔细找一下,会发现生成的代码如下
原来使用的是embed html tag。
我们现在需要获得代表media player的对象,然后控制它停止播放和开始播放。我们先添加两个按钮,并增加对应的javascript函数。javascript函数添加在head标签里面:
f1:m0意思是ice:form的id为f1,而里面的ice:outputMedia的id为m0。这里的stop和play方法首字母也可大写,但是controls的首字母必须小写。
其余代码如下:
下面的资源是微软官方参考,对全面了解media player很有帮助。
http://msdn.microsoft.com/en-us/library/dd564583%28VS.85%29.aspx
我试着将ice:outputMedia的属性mimeType设置为"application/x-ms-wmp",但是在我的例子中,生成的结果仍然是type="application/x-mplayer2"。
现在,添加如下代码:
运行效果如下:
运行状态是数字,具体代表的含义请参考:http://msdn.microsoft.com/en-us/library/dd564085%28VS.85%29.aspx
到目前为止,我已经能够控制Player.Controls对象的方法,并处理Player的StateChange事件。基本达到了我的要求。后面,要看一下IE浏览器下有什么差别。
JavaScript脚本执行错误,函数fnGetMedia返回的对象为null。主要原因是IE需要使用object和classid来代表ActiveX控件,微软总是不愿意完全遵守web标准。这时候,ice:outputMedia生成的html代码和先前有所区别,如下:
这时候,fnGetMedia函数中的var p=document.getElementById("f1:m0")得到的p就是Player.Controls对象。所以只需要直接返回即可。现在,修改一下代码,使得函数能够适应IE和Firefox两种浏览器。
function fnGetMedia(){
var player=document.getElementById("f1:m0");
if(player==null)
return null;
if(player.controls!=null){
return player.controls;
}else{
return player;
}
}
符合潮流,不要去判断浏览器,而判断当前浏览器是否支持需要的功能。因为浏览器太多了(上百种),没有办法判断完。所幸,除了微软的IE,大多数其他主流浏览器都和web标准比较接近。
Firefox下的事件函数需要修改为如下形式:
一个值得注意的事情是,同一个事件可能会多次调用一个函数,事件函数必须要防止这种事情导致的错误。比较好的判断方法是每次将事件类别(eventType)保存到隐藏tag中,下一次收到的如果和上一次的eventType相同,则说明是重复的,可以忽略,只有不同才认为有效。
这个很简单,两种事件处理机制都写上去就行了。如下面的代码: