package railo.runtime.tag; import java.awt.Color; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.collections.map.ReferenceMap; import railo.commons.color.ColorCaster; import railo.commons.io.res.Resource; import railo.commons.io.res.type.file.FileResource; import railo.commons.lang.StringUtil; import railo.runtime.PageContext; import railo.runtime.PageSource; import railo.runtime.exp.ApplicationException; import railo.runtime.exp.ExpressionException; import railo.runtime.exp.PageException; import railo.runtime.ext.tag.BodyTagSupport; import railo.runtime.functions.string.JSStringFormat; import railo.runtime.op.Caster; import railo.runtime.op.Decision; import railo.runtime.type.Collection.Key; import railo.runtime.type.Struct; import railo.runtime.video.VideoInput; import railo.runtime.video.VideoInputImpl; import railo.runtime.video.VideoUtilImpl; /** * implementation of the tag Compiler */ public class VideoPlayerJW extends BodyTagSupport { private static final int TYPE_NONE = 0; private static final int TYPE_PLAYLIST = 1; private static final int TYPE_CHAPTERS = 2; private static final int PLAYLIST_NONE = 0; private static final int PLAYLIST_RIGHT = 1; private static final int PLAYLIST_BOTTOM = 2; private static Color BG_COLOR=new Color(51,51,51); private static Color FG_COLOR=new Color(198,198,198); private String video=null; private boolean autostart=false; private railo.runtime.video.Range showPlay=railo.runtime.video.Range.TRUE; private railo.runtime.video.Range showPause=railo.runtime.video.Range.TRUE; private railo.runtime.video.Range showTimeline=railo.runtime.video.Range.TRUE; private List params=new ArrayList(); private java.awt.Color bgcolor=BG_COLOR; private java.awt.Color fgcolor=FG_COLOR; private java.awt.Color screencolor=null; private java.awt.Color lightcolor=null; private int width=-1; private int height=-1; private boolean debug; private boolean allowfullscreen; private String strWidth; private String strHeight; private static Map sizes=new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT); // JW private Struct passthrough=null; private String preview; private boolean group=false; private boolean playlistThumbnails=true; private int playlistSize=-1; private int playlist=PLAYLIST_NONE; private String target="_self"; private boolean linkfromdisplay; private String overstretch; private boolean download; private String id; private String align; private static int _id=0; public VideoPlayerJW() { } @Override public void release() { super.release(); video=null; autostart=false; showPlay=railo.runtime.video.Range.TRUE; showPause=railo.runtime.video.Range.TRUE; showTimeline=railo.runtime.video.Range.TRUE; params.clear(); debug=false; id=null; group=false; playlist = PLAYLIST_NONE; playlistSize=-1; playlistThumbnails=true; target="_self"; linkfromdisplay=false; overstretch=null; /*group="yes" playlist="right,bottom,none" playlistSize="300" playlistThumbnails="300" */ align=null; bgcolor=BG_COLOR; fgcolor=FG_COLOR; screencolor=null; lightcolor=null; width=-1; height=-1; strWidth=null; strHeight=null; // JW passthrough=null; preview=null; allowfullscreen=false; download=false; } protected void setParam(VideoPlayerParamBean param) { params.add(param); } /** * @param video the video to set */ public void setVideo(String video) { this.video = video; } /** * @param autostart the autostart to set */ public void setAutostart(boolean autostart) { this.autostart = autostart; } /** * @param showPlay the showPlay to set * @throws PageException */ public void setShowplay(String showPlay) throws PageException { this.showPlay = railo.runtime.video.Range.toRange(showPlay); } public void setId(String id) throws PageException { this.id=Caster.toVariableName(id); } /** * @param showPause the showPause to set * @throws PageException */ public void setShowpause(String showPause) throws PageException { this.showPause = railo.runtime.video.Range.toRange(showPause); } /** * @param showTimeline the showTimeline to set * @throws PageException */ public void setShowtimeline(String showTimeline) throws PageException { this.showTimeline = railo.runtime.video.Range.toRange(showTimeline); } /** * @param color the background color to set * @throws PageException */ public void setBgcolor(String color) throws PageException { this.bgcolor = ColorCaster.toColor(color); } public void setBackgroundcolor(String color) throws PageException { setBgcolor(color); } public void setBackground(String color) throws PageException { setBgcolor(color); } public void setScreencolor(String color) throws PageException { this.screencolor = ColorCaster.toColor(color); } public void setLightcolor(String color) throws PageException { this.lightcolor = ColorCaster.toColor(color); } /** * @param color the background color to set * @throws PageException */ public void setFgcolor(String color) throws PageException { this.fgcolor = ColorCaster.toColor(color); } public void setForeground(String color) throws PageException { setFgcolor(color); } public void setForegroundcolor(String color) throws PageException { setFgcolor(color); } /** * @param width the width to set */ public void setWidth(String strWidth) { this.strWidth = strWidth; this.width = Caster.toIntValue(strWidth,-1); } /** * @param height the height to set */ public void setHeight(String strHeight) { this.strHeight = strHeight; this.height = Caster.toIntValue(strHeight,-1); } @Override public int doStartTag() throws PageException { return EVAL_BODY_INCLUDE; } public int doEndTag() throws PageException { // fill top video to params if(video!=null) { VideoPlayerParamBean vppb = new VideoPlayerParamBean(); vppb.setVideo(pageContext,video); if(!StringUtil.isEmpty(preview))vppb.setImage(pageContext,preview); params.add(vppb); } else { if(!StringUtil.isEmpty(preview)) throw new ApplicationException("attribute [preview] is only allowed when attribute [video] is used"); } if(params.size()==0) throw new ApplicationException("you have to define at least one video source"); // calculate dimension int[] dim = calculateDimension(pageContext,params,width,strWidth,height,strHeight); //print.out(width+":"+height); //print.out(strWidth+":"+strHeight); width=dim[0]; height=dim[1]; //print.out(width+":"+height); // playlist int dspHeight=-1,dspWidth=-1; if(playlist!=PLAYLIST_NONE) { if(playlistSize<20)playlistSize=playlist==PLAYLIST_BOTTOM?100:200; if(playlist==PLAYLIST_BOTTOM) { dspHeight=height; height+=playlistSize; } else { dspWidth=width; width+=playlistSize; } } else playlistThumbnails=false; VideoPlayerParamBean param; String id=getId();// String placeholderId="ph_"+id; String flashId="swf_"+id; StringBuffer sb=new StringBuffer(); write(sb,"<script type=\"text/javascript\" src=\"/railo-context/swfobject.js.cfm\"></script>"); write(sb,"<div "); if(passthrough!=null) { Iterator<Entry<Key, Object>> it = passthrough.entryIterator(); Entry<Key, Object> e; String key; while(it.hasNext()) { e = it.next(); key=e.getKey().getString(); if(StringUtil.startsWithIgnoreCase(key, "div.")) write(sb,key.substring(4)+"=\""+Caster.toString(e.getValue())+"\" "); } } write(sb,(align!=null?"align=\""+align+"\"":"")+" id=\""+placeholderId+"\"><a href=\"http://www.macromedia.com/go/getflashplayer\">Get the Flash Player</a> to see this player.</a></div>"); write(sb,"<script type=\"text/javascript\">\n"); write(sb,"var so = new SWFObject(\"/railo-context/mediaplayer.swf.cfm\", \""+flashId+"\", \""+width+"\", \""+(height)+"\", \"8\", \""+format("#",bgcolor)+"\");\n"); // script addParam(sb,"allowscriptaccess","always"); addVariable(sb,"enablejs","true"); addVariable(sb,"javascriptid",flashId); addVariable(sb,"shuffle","false"); addVariable(sb,"linktarget",target); addVariable(sb,"linkfromdisplay",Caster.toString(linkfromdisplay)); addVariable(sb,"abouttxt","Railo Video Player"); addVariable(sb,"aboutlnk","http://www.getrailo.org"); // control addParam(sb,"allowfullscreen",Caster.toString(allowfullscreen)); addParam(sb,"usefullscreen",Caster.toString(allowfullscreen)); addVariable(sb,"autostart",Caster.toString(autostart)); if(!StringUtil.isEmpty(overstretch))addVariable(sb,"overstretch",overstretch); addVariable(sb,"showdownload",Caster.toString(download)); // color if(lightcolor==null)lightcolor=fgcolor.brighter(); if(screencolor==null)screencolor=Color.BLACK;//fgcolor.brighter(); addVariable(sb,"backcolor",format("0x",bgcolor)); addVariable(sb,"frontcolor",format("0x",fgcolor)); addVariable(sb,"lightcolor",format("0x",lightcolor)); addVariable(sb,"screencolor",format("0x",screencolor)); if(passthrough!=null) { Iterator<Entry<Key, Object>> it = passthrough.entryIterator(); Entry<Key, Object> e; String key; while(it.hasNext()) { e = it.next(); key=e.getKey().getString(); if(StringUtil.startsWithIgnoreCase(key, "param.")) addParam(sb,key.substring(6),Caster.toString(e.getValue())); else if(StringUtil.startsWithIgnoreCase(key, "variable.")) addVariable(sb,key.substring(9),Caster.toString(e.getValue())); else if(StringUtil.startsWithIgnoreCase(key, "div.")); else addVariable(sb,key,Caster.toString(e.getValue())); } } if(params.size()>1 && group) addVariable(sb,"repeat","true"); /*if(playlist!=PLAYLIST_NONE) { if(playlistSize<20)playlistSize=playlist==PLAYLIST_BOTTOM?300:200; if(playlist==PLAYLIST_BOTTOM) { addVariable(sb,"displayheight",Caster.toString(height)); height+=playlistSize; } else { addVariable(sb,"displaywidth",Caster.toString(width)); width+=playlistSize; } if(playlistThumbnails && hasImages())addVariable(sb,"thumbsinplaylist","true"); }*/ // dimension if(dspWidth>0)addVariable(sb,"displaywidth",Caster.toString(dspWidth)); if(dspHeight>0)addVariable(sb,"displayheight",Caster.toString(dspHeight)); addVariable(sb,"width",Caster.toString(width)); addVariable(sb,"height",Caster.toString(height)); if(playlistThumbnails && hasImages())addVariable(sb,"thumbsinplaylist","true"); //if(preview!=null) addVariable(sb,"image",toPath(preview)); //Iterator it = params.iterator(); //addVariable("file","/rvp/videos/David.flv"); //addVariable("captions","http://localhost:8080/caption.cfm"); //while(it.hasNext()) { //param=(VideoPlayerParamBean) it.next(); //addVariable(sb,"file",toPath(param.getResource())); //break; //} //addVariable("image","video.jpg"); write(sb,"so.write(\""+placeholderId+"\");\n"); //if(params.size()>1) { Iterator it = params.iterator(); while(it.hasNext()) { param=(VideoPlayerParamBean) it.next(); addItem(sb,flashId,param); } //} write(sb,"</script>"); try { if(debug) { pageContext.forceWrite("<pre>"+StringUtil.replace(sb.toString(), "<", "<", false)+"</pre>"); } pageContext.forceWrite(sb.toString()); } catch (IOException e) { } return EVAL_PAGE; } private synchronized String getId() { if(!StringUtil.isEmpty(id)) return id; _id++; if(_id<0) _id=1; return ""+_id; } private boolean hasImages() { Iterator it = params.iterator(); while(it.hasNext()) { if(((VideoPlayerParamBean) it.next()).getImage()!=null) return true; } return false; } private void addItem(StringBuffer sb, String id, VideoPlayerParamBean param) { //sb.append("setTimeout('thisMovie(\""+id+"\").addItem({file:\""+JSStringFormat.invoke(path)+"\"},null);',1000);\n"); // file String file = "file:'"+JSStringFormat.invoke(toPath(param.getResource()))+"'"; // image String image=""; if(param.getImage()!=null) { image=",image:'"+JSStringFormat.invoke(toPath(param.getImage()))+"'"; } // title String title=""; if(!StringUtil.isEmpty(param.getTitle())) { title=",title:'"+JSStringFormat.invoke(param.getTitle())+"'"; } // link String link=""; if(!StringUtil.isEmpty(param.getLink())) { link=",link:'"+JSStringFormat.invoke(param.getLink())+"'"; } // author String author=""; if(!StringUtil.isEmpty(param.getAuthor())) { author=",author:'"+JSStringFormat.invoke(param.getAuthor())+"'"; } sb.append("addItem('"+id+"',{"+file+title+image+link+author+"});\n"); } private void addVariable(StringBuffer sb, String name, String value) { value=JSStringFormat.invoke(value); if(!(value.equals("false") || value.equals("true"))) value="'"+value+"'"; sb.append("so.addVariable('"+JSStringFormat.invoke(name)+"',"+value+");\n"); } private void addParam(StringBuffer sb,String name, String value) { sb.append("so.addParam('"+name+"','"+value+"');\n"); } private static int[] calculateDimension(PageContext pc,List params,int width, String strWidth,int height, String strHeight) throws PageException { Iterator it = params.iterator(); ArrayList sources=new ArrayList(); //Resource[] sources=new Resource[params.size()]; VideoPlayerParamBean param; while(it.hasNext()) { param = (VideoPlayerParamBean) it.next(); if(param.getVideo()!=null) sources.add(new VideoInputImpl(param.getVideo())); } return VideoUtilImpl.getInstance().calculateDimension(pc, (VideoInput[])sources.toArray(new VideoInput[sources.size()]), width, strWidth, height, strHeight); } private String toPath(Resource res) { if(!(res instanceof FileResource)) return res.getAbsolutePath(); //Config config=pageContext.getConfig(); PageSource ps = pageContext.toPageSource(res,null); if(ps==null) return res.getAbsolutePath(); String realPath = ps.getRealpath(); realPath=realPath.replace('\\', '/'); if(realPath.endsWith("/"))realPath=realPath.substring(0,realPath.length()-1); //print.out("real:"+realPath); String mapping=ps.getMapping().getVirtual(); mapping=mapping.replace('\\', '/'); if(mapping.endsWith("/"))mapping=mapping.substring(0,mapping.length()-1); return mapping+realPath; } private void write(StringBuffer sb, String string) { sb.append(string); } private static String format(String prefix, Color color) { return prefix+toHex(color.getRed())+toHex(color.getGreen())+toHex(color.getBlue()); } private static String toHex(int value) { String str = Integer.toHexString(value); if(str.length()==1) return "0".concat(str); return str; } /** * @param debug the debug to set */ public void setDebug(boolean debug) { this.debug = debug; } /** * @param passthrough the passthrough to set */ public void setPassthrough(Struct passthrough) { this.passthrough = passthrough; } /** * @param preview the preview to set * @throws ExpressionException */ public void setPreview(String preview) { this.preview = preview;//ResourceUtil.toResourceExisting(pageContext, preview); } /** * @param allowfullscreen the allowfullscreen to set */ public void setAllowfullscreen(boolean allowfullscreen) { this.allowfullscreen = allowfullscreen; } public void setAlign(String strAlign) throws ApplicationException { if(StringUtil.isEmpty(strAlign)) return; strAlign=strAlign.trim().toLowerCase(); if("right".equals(strAlign)) this.align = "right"; else if("center".equals(strAlign)) this.align = "center"; else if("left".equals(strAlign)) this.align = "left"; else throw new ApplicationException("invalid value for attribute align ["+strAlign+"], valid values are [left,center,right]"); } /** * @param group the group to set */ public void setGroup(boolean group) { this.group = group; } public void setLinktarget(String target) { this.target = target; } public void setTarget(String target) { this.target = target; } public void setLinkfromdisplay(boolean linkfromdisplay) { this.linkfromdisplay = linkfromdisplay; } /** * @param playlistThumbnails the playlistThumbnails to set */ public void setPlaylistthumbnails(boolean playlistThumbnails) { this.playlistThumbnails = playlistThumbnails; } public void setThumbnails(boolean playlistThumbnails) { setPlaylistthumbnails(playlistThumbnails); } public void setThumbs(boolean playlistThumbnails) { setPlaylistthumbnails(playlistThumbnails); } /** * @param playlistSize the playlistSize to set */ public void setPlaylistsize(double playlistSize) throws ApplicationException { if(playlistSize<=40) throw new ApplicationException("playlist size has to be a positive number, at least 41px"); this.playlistSize = (int) playlistSize; } /** * @param playlist the playlist to set */ public void setPlaylist(String strPlaylist) throws PageException { strPlaylist=strPlaylist.trim().toLowerCase(); if("right".equals(strPlaylist)) playlist=PLAYLIST_RIGHT; else if("bottom".equals(strPlaylist)) playlist=PLAYLIST_BOTTOM; else if("none".equals(strPlaylist)) playlist=PLAYLIST_NONE; else if(Decision.isBoolean(strPlaylist)) { playlist=Caster.toBooleanValue(strPlaylist)?PLAYLIST_BOTTOM:PLAYLIST_NONE; } else throw new ApplicationException("invalid playlist definition ["+strPlaylist+"], valid values are [right,bottom,none]"); } /** * @param overstretch the overstretch to set */ public void setOverstretch(String overstretch) throws PageException { overstretch=overstretch.trim().toLowerCase(); if("fit".equals(overstretch)) overstretch="fit"; else if("none".equals(overstretch)) overstretch="none"; else if("proportion".equals(overstretch)) overstretch="true"; else if(Decision.isBoolean(overstretch)) { overstretch=Caster.toString(Caster.toBooleanValue(overstretch)); } else throw new ApplicationException("invalid overstretch definition ["+overstretch+"], valid values are [fit,none,true,false]"); this.overstretch = overstretch; } /** * @param download the download to set */ public void setDownload(boolean download) { this.download = download; } }