001 package railo.runtime.tag; 002 003 004 import java.awt.Color; 005 import java.io.IOException; 006 import java.util.ArrayList; 007 import java.util.Iterator; 008 import java.util.List; 009 import java.util.Map; 010 011 import org.apache.commons.collections.map.ReferenceMap; 012 013 import railo.commons.color.ColorCaster; 014 import railo.commons.io.res.Resource; 015 import railo.commons.io.res.type.file.FileResource; 016 import railo.commons.lang.StringUtil; 017 import railo.runtime.PageContext; 018 import railo.runtime.PageSource; 019 import railo.runtime.exp.ApplicationException; 020 import railo.runtime.exp.ExpressionException; 021 import railo.runtime.exp.PageException; 022 import railo.runtime.ext.tag.BodyTagSupport; 023 import railo.runtime.functions.string.JSStringFormat; 024 import railo.runtime.op.Caster; 025 import railo.runtime.op.Decision; 026 import railo.runtime.type.Collection.Key; 027 import railo.runtime.type.Struct; 028 import railo.runtime.video.VideoInput; 029 import railo.runtime.video.VideoInputImpl; 030 import railo.runtime.video.VideoUtilImpl; 031 032 /** 033 * implementation of the tag Compiler 034 */ 035 public class VideoPlayerJW extends BodyTagSupport { 036 037 private static final int TYPE_NONE = 0; 038 private static final int TYPE_PLAYLIST = 1; 039 private static final int TYPE_CHAPTERS = 2; 040 041 private static final int PLAYLIST_NONE = 0; 042 private static final int PLAYLIST_RIGHT = 1; 043 private static final int PLAYLIST_BOTTOM = 2; 044 045 private static Color BG_COLOR=new Color(51,51,51); 046 private static Color FG_COLOR=new Color(198,198,198); 047 048 private String video=null; 049 private boolean autostart=false; 050 051 private railo.runtime.video.Range showPlay=railo.runtime.video.Range.TRUE; 052 private railo.runtime.video.Range showPause=railo.runtime.video.Range.TRUE; 053 private railo.runtime.video.Range showTimeline=railo.runtime.video.Range.TRUE; 054 private List params=new ArrayList(); 055 private java.awt.Color bgcolor=BG_COLOR; 056 private java.awt.Color fgcolor=FG_COLOR; 057 private java.awt.Color screencolor=null; 058 private java.awt.Color lightcolor=null; 059 060 061 062 private int width=-1; 063 private int height=-1; 064 private boolean debug; 065 private boolean allowfullscreen; 066 private String strWidth; 067 private String strHeight; 068 private static Map sizes=new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT); 069 070 // JW 071 private Struct passthrough=null; 072 private String preview; 073 074 private boolean group=false; 075 private boolean playlistThumbnails=true; 076 private int playlistSize=-1; 077 private int playlist=PLAYLIST_NONE; 078 private String target="_self"; 079 private boolean linkfromdisplay; 080 private String overstretch; 081 private boolean download; 082 private String id; 083 private String align; 084 private static int _id=0; 085 086 public VideoPlayerJW() { 087 088 } 089 090 /** 091 * @see javax.servlet.jsp.tagext.Tag#release() 092 */ 093 public void release() { 094 super.release(); 095 video=null; 096 autostart=false; 097 098 showPlay=railo.runtime.video.Range.TRUE; 099 showPause=railo.runtime.video.Range.TRUE; 100 showTimeline=railo.runtime.video.Range.TRUE; 101 params.clear(); 102 debug=false; 103 104 id=null; 105 group=false; 106 playlist = PLAYLIST_NONE; 107 playlistSize=-1; 108 playlistThumbnails=true; 109 target="_self"; 110 linkfromdisplay=false; 111 overstretch=null; 112 /*group="yes" 113 playlist="right,bottom,none" 114 playlistSize="300" 115 playlistThumbnails="300" 116 117 */ 118 align=null; 119 120 121 bgcolor=BG_COLOR; 122 fgcolor=FG_COLOR; 123 screencolor=null; 124 lightcolor=null; 125 width=-1; 126 height=-1; 127 128 strWidth=null; 129 strHeight=null; 130 131 // JW 132 passthrough=null; 133 preview=null; 134 allowfullscreen=false; 135 download=false; 136 } 137 138 139 140 protected void setParam(VideoPlayerParamBean param) { 141 params.add(param); 142 } 143 144 /** 145 * @param video the video to set 146 */ 147 public void setVideo(String video) { 148 this.video = video; 149 } 150 151 /** 152 * @param autostart the autostart to set 153 */ 154 public void setAutostart(boolean autostart) { 155 this.autostart = autostart; 156 } 157 158 /** 159 * @param showPlay the showPlay to set 160 * @throws PageException 161 */ 162 public void setShowplay(String showPlay) throws PageException { 163 this.showPlay = railo.runtime.video.Range.toRange(showPlay); 164 } 165 public void setId(String id) throws PageException { 166 this.id=Caster.toVariableName(id); 167 } 168 169 /** 170 * @param showPause the showPause to set 171 * @throws PageException 172 */ 173 public void setShowpause(String showPause) throws PageException { 174 this.showPause = railo.runtime.video.Range.toRange(showPause); 175 } 176 177 /** 178 * @param showTimeline the showTimeline to set 179 * @throws PageException 180 */ 181 public void setShowtimeline(String showTimeline) throws PageException { 182 this.showTimeline = railo.runtime.video.Range.toRange(showTimeline); 183 } 184 185 /** 186 * @param color the background color to set 187 * @throws PageException 188 */ 189 public void setBgcolor(String color) throws PageException { 190 this.bgcolor = ColorCaster.toColor(color); 191 } 192 public void setBackgroundcolor(String color) throws PageException { 193 setBgcolor(color); 194 } 195 public void setBackground(String color) throws PageException { 196 setBgcolor(color); 197 } 198 public void setScreencolor(String color) throws PageException { 199 this.screencolor = ColorCaster.toColor(color); 200 } 201 public void setLightcolor(String color) throws PageException { 202 this.lightcolor = ColorCaster.toColor(color); 203 } 204 205 206 /** 207 * @param color the background color to set 208 * @throws PageException 209 */ 210 public void setFgcolor(String color) throws PageException { 211 this.fgcolor = ColorCaster.toColor(color); 212 } 213 214 public void setForeground(String color) throws PageException { 215 setFgcolor(color); 216 } 217 218 public void setForegroundcolor(String color) throws PageException { 219 setFgcolor(color); 220 } 221 222 /** 223 * @param width the width to set 224 */ 225 public void setWidth(String strWidth) { 226 this.strWidth = strWidth; 227 this.width = Caster.toIntValue(strWidth,-1); 228 } 229 230 /** 231 * @param height the height to set 232 */ 233 public void setHeight(String strHeight) { 234 this.strHeight = strHeight; 235 this.height = Caster.toIntValue(strHeight,-1); 236 } 237 238 /** 239 * @throws IOException 240 * @see javax.servlet.jsp.tagext.Tag#doStartTag() 241 */ 242 public int doStartTag() throws PageException { 243 return EVAL_BODY_INCLUDE; 244 } 245 public int doEndTag() throws PageException { 246 247 // fill top video to params 248 if(video!=null) { 249 VideoPlayerParamBean vppb = new VideoPlayerParamBean(); 250 vppb.setVideo(pageContext,video); 251 if(!StringUtil.isEmpty(preview))vppb.setImage(pageContext,preview); 252 params.add(vppb); 253 } 254 else { 255 if(!StringUtil.isEmpty(preview)) 256 throw new ApplicationException("attribute [preview] is only allowed when attribute [video] is used"); 257 } 258 259 if(params.size()==0) 260 throw new ApplicationException("you have to define at least one video source"); 261 262 263 264 265 266 // calculate dimension 267 int[] dim = calculateDimension(pageContext,params,width,strWidth,height,strHeight); 268 269 //print.out(width+":"+height); 270 //print.out(strWidth+":"+strHeight); 271 width=dim[0]; 272 height=dim[1]; 273 274 //print.out(width+":"+height); 275 276 277 // playlist 278 int dspHeight=-1,dspWidth=-1; 279 if(playlist!=PLAYLIST_NONE) { 280 if(playlistSize<20)playlistSize=playlist==PLAYLIST_BOTTOM?100:200; 281 if(playlist==PLAYLIST_BOTTOM) { 282 dspHeight=height; 283 height+=playlistSize; 284 } 285 else { 286 dspWidth=width; 287 width+=playlistSize; 288 } 289 } 290 else playlistThumbnails=false; 291 292 293 VideoPlayerParamBean param; 294 295 296 String id=getId();// 297 String placeholderId="ph_"+id; 298 String flashId="swf_"+id; 299 300 StringBuffer sb=new StringBuffer(); 301 302 write(sb,"<script type=\"text/javascript\" src=\"/railo-context/swfobject.js.cfm\"></script>"); 303 write(sb,"<div "); 304 305 306 if(passthrough!=null) { 307 Key[] keys = passthrough.keys(); 308 String key; 309 for(int i=0;i<keys.length;i++) { 310 key=keys[i].getString(); 311 if(StringUtil.startsWithIgnoreCase(key, "div.")) 312 write(sb,key.substring(4)+"=\""+Caster.toString(passthrough.get(keys[i]))+"\" "); 313 } 314 } 315 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>"); 316 317 318 319 write(sb,"<script type=\"text/javascript\">\n"); 320 write(sb,"var so = new SWFObject(\"/railo-context/mediaplayer.swf.cfm\", \""+flashId+"\", \""+width+"\", \""+(height)+"\", \"8\", \""+format("#",bgcolor)+"\");\n"); 321 322 // script 323 addParam(sb,"allowscriptaccess","always"); 324 addVariable(sb,"enablejs","true"); 325 addVariable(sb,"javascriptid",flashId); 326 327 addVariable(sb,"shuffle","false"); 328 addVariable(sb,"linktarget",target); 329 addVariable(sb,"linkfromdisplay",Caster.toString(linkfromdisplay)); 330 addVariable(sb,"abouttxt","Railo Video Player"); 331 addVariable(sb,"aboutlnk","http://www.getrailo.org"); 332 333 // control 334 addParam(sb,"allowfullscreen",Caster.toString(allowfullscreen)); 335 addParam(sb,"usefullscreen",Caster.toString(allowfullscreen)); 336 addVariable(sb,"autostart",Caster.toString(autostart)); 337 if(!StringUtil.isEmpty(overstretch))addVariable(sb,"overstretch",overstretch); 338 addVariable(sb,"showdownload",Caster.toString(download)); 339 340 341 342 343 // color 344 if(lightcolor==null)lightcolor=fgcolor.brighter(); 345 if(screencolor==null)screencolor=Color.BLACK;//fgcolor.brighter(); 346 addVariable(sb,"backcolor",format("0x",bgcolor)); 347 addVariable(sb,"frontcolor",format("0x",fgcolor)); 348 addVariable(sb,"lightcolor",format("0x",lightcolor)); 349 addVariable(sb,"screencolor",format("0x",screencolor)); 350 351 if(passthrough!=null) { 352 Key[] keys = passthrough.keys(); 353 String key; 354 for(int i=0;i<keys.length;i++) { 355 key=keys[i].getString(); 356 if(StringUtil.startsWithIgnoreCase(key, "param.")) 357 addParam(sb,key.substring(6),Caster.toString(passthrough.get(keys[i]))); 358 else if(StringUtil.startsWithIgnoreCase(key, "variable.")) 359 addVariable(sb,key.substring(9),Caster.toString(passthrough.get(keys[i]))); 360 else if(StringUtil.startsWithIgnoreCase(key, "div.")); 361 else 362 addVariable(sb,key,Caster.toString(passthrough.get(keys[i]))); 363 } 364 } 365 366 if(params.size()>1 && group) addVariable(sb,"repeat","true"); 367 368 /*if(playlist!=PLAYLIST_NONE) { 369 if(playlistSize<20)playlistSize=playlist==PLAYLIST_BOTTOM?300:200; 370 if(playlist==PLAYLIST_BOTTOM) { 371 addVariable(sb,"displayheight",Caster.toString(height)); 372 height+=playlistSize; 373 } 374 else { 375 addVariable(sb,"displaywidth",Caster.toString(width)); 376 width+=playlistSize; 377 } 378 if(playlistThumbnails && hasImages())addVariable(sb,"thumbsinplaylist","true"); 379 }*/ 380 381 // dimension 382 if(dspWidth>0)addVariable(sb,"displaywidth",Caster.toString(dspWidth)); 383 if(dspHeight>0)addVariable(sb,"displayheight",Caster.toString(dspHeight)); 384 addVariable(sb,"width",Caster.toString(width)); 385 addVariable(sb,"height",Caster.toString(height)); 386 if(playlistThumbnails && hasImages())addVariable(sb,"thumbsinplaylist","true"); 387 388 //if(preview!=null) addVariable(sb,"image",toPath(preview)); 389 //Iterator it = params.iterator(); 390 //addVariable("file","/rvp/videos/David.flv"); 391 //addVariable("captions","http://localhost:8080/caption.cfm"); 392 //while(it.hasNext()) { 393 //param=(VideoPlayerParamBean) it.next(); 394 //addVariable(sb,"file",toPath(param.getResource())); 395 //break; 396 //} 397 //addVariable("image","video.jpg"); 398 399 write(sb,"so.write(\""+placeholderId+"\");\n"); 400 //if(params.size()>1) { 401 Iterator it = params.iterator(); 402 while(it.hasNext()) { 403 param=(VideoPlayerParamBean) it.next(); 404 addItem(sb,flashId,param); 405 } 406 //} 407 write(sb,"</script>"); 408 try { 409 if(debug) { 410 pageContext.forceWrite("<pre>"+StringUtil.replace(sb.toString(), "<", "<", false)+"</pre>"); 411 } 412 pageContext.forceWrite(sb.toString()); 413 414 415 } 416 catch (IOException e) { 417 418 } 419 return EVAL_PAGE; 420 } 421 422 private synchronized String getId() { 423 if(!StringUtil.isEmpty(id)) return id; 424 _id++; 425 if(_id<0) _id=1; 426 return ""+_id; 427 } 428 429 private boolean hasImages() { 430 Iterator it = params.iterator(); 431 while(it.hasNext()) { 432 if(((VideoPlayerParamBean) it.next()).getImage()!=null) return true; 433 } 434 return false; 435 } 436 437 private void addItem(StringBuffer sb, String id, VideoPlayerParamBean param) { 438 //sb.append("setTimeout('thisMovie(\""+id+"\").addItem({file:\""+JSStringFormat.invoke(path)+"\"},null);',1000);\n"); 439 440 // file 441 String file = "file:'"+JSStringFormat.invoke(toPath(param.getResource()))+"'"; 442 443 // image 444 String image=""; 445 if(param.getImage()!=null) { 446 image=",image:'"+JSStringFormat.invoke(toPath(param.getImage()))+"'"; 447 } 448 449 // title 450 String title=""; 451 if(!StringUtil.isEmpty(param.getTitle())) { 452 title=",title:'"+JSStringFormat.invoke(param.getTitle())+"'"; 453 } 454 455 // link 456 String link=""; 457 if(!StringUtil.isEmpty(param.getLink())) { 458 link=",link:'"+JSStringFormat.invoke(param.getLink())+"'"; 459 } 460 461 // author 462 String author=""; 463 if(!StringUtil.isEmpty(param.getAuthor())) { 464 author=",author:'"+JSStringFormat.invoke(param.getAuthor())+"'"; 465 } 466 467 sb.append("addItem('"+id+"',{"+file+title+image+link+author+"});\n"); 468 } 469 470 private void addVariable(StringBuffer sb, String name, String value) { 471 value=JSStringFormat.invoke(value); 472 if(!(value.equals("false") || value.equals("true"))) 473 value="'"+value+"'"; 474 sb.append("so.addVariable('"+JSStringFormat.invoke(name)+"',"+value+");\n"); 475 } 476 477 private void addParam(StringBuffer sb,String name, String value) { 478 sb.append("so.addParam('"+name+"','"+value+"');\n"); 479 } 480 481 private static int[] calculateDimension(PageContext pc,List params,int width, String strWidth,int height, String strHeight) throws PageException { 482 Iterator it = params.iterator(); 483 ArrayList sources=new ArrayList(); 484 //Resource[] sources=new Resource[params.size()]; 485 VideoPlayerParamBean param; 486 487 while(it.hasNext()) { 488 param = (VideoPlayerParamBean) it.next(); 489 if(param.getVideo()!=null) 490 sources.add(new VideoInputImpl(param.getVideo())); 491 } 492 return VideoUtilImpl.getInstance().calculateDimension(pc, (VideoInput[])sources.toArray(new VideoInput[sources.size()]), width, strWidth, height, strHeight); 493 494 } 495 496 private String toPath(Resource res) { 497 if(!(res instanceof FileResource)) return res.getAbsolutePath(); 498 499 //Config config=pageContext.getConfig(); 500 PageSource ps = pageContext.toPageSource(res,null); 501 if(ps==null) return res.getAbsolutePath(); 502 503 String realPath = ps.getRealpath(); 504 realPath=realPath.replace('\\', '/'); 505 if(realPath.endsWith("/"))realPath=realPath.substring(0,realPath.length()-1); 506 507 //print.out("real:"+realPath); 508 String mapping=ps.getMapping().getVirtual(); 509 mapping=mapping.replace('\\', '/'); 510 if(mapping.endsWith("/"))mapping=mapping.substring(0,mapping.length()-1); 511 512 return mapping+realPath; 513 514 515 } 516 517 518 519 private void write(StringBuffer sb, String string) { 520 sb.append(string); 521 } 522 523 524 525 private static String format(String prefix, Color color) { 526 return prefix+toHex(color.getRed())+toHex(color.getGreen())+toHex(color.getBlue()); 527 } 528 529 530 531 private static String toHex(int value) { 532 String str = Integer.toHexString(value); 533 if(str.length()==1) return "0".concat(str); 534 return str; 535 } 536 537 /** 538 * @param debug the debug to set 539 */ 540 public void setDebug(boolean debug) { 541 this.debug = debug; 542 } 543 544 /** 545 * @param passthrough the passthrough to set 546 */ 547 public void setPassthrough(Struct passthrough) { 548 this.passthrough = passthrough; 549 } 550 551 /** 552 * @param preview the preview to set 553 * @throws ExpressionException 554 */ 555 public void setPreview(String preview) { 556 this.preview = preview;//ResourceUtil.toResourceExisting(pageContext, preview); 557 } 558 559 /** 560 * @param allowfullscreen the allowfullscreen to set 561 */ 562 public void setAllowfullscreen(boolean allowfullscreen) { 563 this.allowfullscreen = allowfullscreen; 564 } 565 566 public void setAlign(String strAlign) throws ApplicationException { 567 if(StringUtil.isEmpty(strAlign)) return; 568 strAlign=strAlign.trim().toLowerCase(); 569 if("right".equals(strAlign)) this.align = "right"; 570 else if("center".equals(strAlign)) this.align = "center"; 571 else if("left".equals(strAlign)) this.align = "left"; 572 else 573 throw new ApplicationException("invalid value for attribute align ["+strAlign+"], valid values are [left,center,right]"); 574 } 575 576 /** 577 * @param group the group to set 578 */ 579 public void setGroup(boolean group) { 580 this.group = group; 581 } 582 public void setLinktarget(String target) { 583 this.target = target; 584 } 585 public void setTarget(String target) { 586 this.target = target; 587 } 588 public void setLinkfromdisplay(boolean linkfromdisplay) { 589 this.linkfromdisplay = linkfromdisplay; 590 } 591 592 /** 593 * @param playlistThumbnails the playlistThumbnails to set 594 */ 595 public void setPlaylistthumbnails(boolean playlistThumbnails) { 596 this.playlistThumbnails = playlistThumbnails; 597 } 598 public void setThumbnails(boolean playlistThumbnails) { 599 setPlaylistthumbnails(playlistThumbnails); 600 } 601 public void setThumbs(boolean playlistThumbnails) { 602 setPlaylistthumbnails(playlistThumbnails); 603 } 604 605 /** 606 * @param playlistSize the playlistSize to set 607 */ 608 public void setPlaylistsize(double playlistSize) throws ApplicationException { 609 if(playlistSize<=40) throw new ApplicationException("playlist size has to be a positive number, at least 41px"); 610 this.playlistSize = (int) playlistSize; 611 } 612 613 /** 614 * @param playlist the playlist to set 615 */ 616 public void setPlaylist(String strPlaylist) throws PageException { 617 strPlaylist=strPlaylist.trim().toLowerCase(); 618 if("right".equals(strPlaylist)) playlist=PLAYLIST_RIGHT; 619 else if("bottom".equals(strPlaylist)) playlist=PLAYLIST_BOTTOM; 620 else if("none".equals(strPlaylist)) playlist=PLAYLIST_NONE; 621 else if(Decision.isBoolean(strPlaylist)) { 622 playlist=Caster.toBooleanValue(strPlaylist)?PLAYLIST_BOTTOM:PLAYLIST_NONE; 623 } 624 else throw new ApplicationException("invalid playlist definition ["+strPlaylist+"], valid values are [right,bottom,none]"); 625 } 626 627 /** 628 * @param overstretch the overstretch to set 629 */ 630 public void setOverstretch(String overstretch) throws PageException { 631 overstretch=overstretch.trim().toLowerCase(); 632 if("fit".equals(overstretch)) overstretch="fit"; 633 else if("none".equals(overstretch)) overstretch="none"; 634 else if("proportion".equals(overstretch)) overstretch="true"; 635 else if(Decision.isBoolean(overstretch)) { 636 overstretch=Caster.toString(Caster.toBooleanValue(overstretch)); 637 } 638 else throw new ApplicationException("invalid overstretch definition ["+overstretch+"], valid values are [fit,none,true,false]"); 639 640 this.overstretch = overstretch; 641 } 642 643 /** 644 * @param download the download to set 645 */ 646 public void setDownload(boolean download) { 647 this.download = download; 648 } 649 650 }