package railo.runtime.video;
import java.util.Map;
import org.apache.commons.collections.map.ReferenceMap;
import railo.commons.io.res.Resource;
import railo.commons.io.res.type.file.FileResource;
import railo.commons.io.res.type.http.HTTPResource;
import railo.commons.lang.ClassException;
import railo.commons.lang.ClassUtil;
import railo.commons.lang.StringUtil;
import railo.runtime.PageContext;
import railo.runtime.config.Config;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.ExpressionException;
import railo.runtime.exp.PageException;
import railo.runtime.functions.string.Hash;
import railo.runtime.op.Caster;
public class VideoUtilImpl implements VideoUtil {
private static Map sizes=new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT);
private static VideoUtilImpl instance=new VideoUtilImpl();
private VideoUtilImpl(){ }
public static VideoUtilImpl getInstance() {
return instance;
}
/**
* @see railo.runtime.video.VideoUtil#createVideoInput(railo.commons.io.res.Resource)
*/
public VideoInput createVideoInput(Resource input) {
return new VideoInputImpl(input);
}
/**
* @see railo.runtime.video.VideoUtil#createVideoOutput(railo.commons.io.res.Resource)
*/
public VideoOutput createVideoOutput(Resource output) {
return new VideoOutputImpl(output);
}
/**
* @see railo.runtime.video.VideoUtil#createVideoProfile()
*/
public VideoProfile createVideoProfile() {
return new VideoProfileImpl();
}
public long toBytes(String byt) throws PageException {
byt=byt.trim().toLowerCase();
if(byt.endsWith("kb/s") || byt.endsWith("kbps")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-4).trim())*1024);
}
if(byt.endsWith("mb/s") || byt.endsWith("mbps")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-4).trim())*1024*1024);
}
if(byt.endsWith("gb/s") || byt.endsWith("gbps")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-4).trim())*1024*1024*1024);
}
if(byt.endsWith("b/s") || byt.endsWith("bps")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-3).trim()));
}
if(byt.endsWith("kbit/s")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-6).trim())*1024);
}
if(byt.endsWith("mbit/s")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-6).trim())*1024*1024);
}
if(byt.endsWith("gbit/s")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-6).trim())*1024*1024*1024);
}
if(byt.endsWith("bit/s")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-5).trim()));
}
if(byt.endsWith("kb")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-2).trim())*1024);
}
if(byt.endsWith("mb")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-2).trim())*1024*1024);
}
if(byt.endsWith("gb")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-2).trim())*1024*1024*1024);
}
if(byt.endsWith("g")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-1).trim())*1024*1024*1024);
}
if(byt.endsWith("m")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-1).trim())*1024*1024);
}
if(byt.endsWith("k")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-1).trim())*1024);
}
if(byt.endsWith("b")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-1).trim()));
}
return Caster.toLongValue(byt);
}
public long toHerz(String byt) throws PageException {
byt=byt.trim().toLowerCase();
if(byt.endsWith("mhz")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-3).trim())*1000*1000);
}
if(byt.endsWith("khz")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-3).trim())*1000);
}
if(byt.endsWith("hz")) {
return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-2).trim()));
}
return Caster.toLongValue(byt);
}
public long toMillis(String time) throws PageException {
int last=0,index=time.indexOf(':');
long hour=Caster.toIntValue(time.substring(last,index).trim());
last=index+1;
index=time.indexOf(':',last);
long minute=Caster.toIntValue(time.substring(last,index).trim());
double seconds=Caster.toDoubleValue(time.substring(index+1).trim());
return (hour*60L*60L*1000L)+(minute*60L*1000L)+((int)(seconds*1000F));
}
public static VideoExecuter createVideoExecuter(Config config) throws ClassException {
Class clazz = config.getVideoExecuterClass();
return (VideoExecuter) ClassUtil.loadInstance(clazz);
}
public int[] calculateDimension(PageContext pc,VideoInput[] sources,int width, String strWidth,int height, String strHeight) throws PageException {
int[] rtn;
if(width!=-1 && height!=-1) {
return new int[]{width,height};
}
// video component not installed
try {
if(VideoUtilImpl.createVideoExecuter(pc.getConfig()) instanceof VideoExecuterNotSupported){
throw new ApplicationException("attributes width/height are required when no video analyser is installed");
}
} catch (ClassException e) {
}
VideoInput source;
// hash
StringBuffer sb=new StringBuffer(strHeight+"-"+strWidth);
for(int i=0;i<sources.length;i++) {
sb.append(sources[i].getResource().toString());
}
// get from casche
String key = Hash.call(pc, sb.toString());
int[] ci=(int[]) sizes.get(key);
if(ci!=null) {
return ci;
}
// getSize
int w=0,h=0;
try {
for(int i=0;i<sources.length;i++) {
source = sources[i];
checkResource(source.getResource());
VideoInfo info = VideoUtilImpl.createVideoExecuter(pc.getConfig()).info(pc.getConfig(),source);
if(w<info.getWidth()) {
h=info.getHeight();
w=info.getWidth();
}
}
}
catch(Exception ve) {
throw Caster.toPageException(ve);
}
// calculate only height
if(width!=-1) {
height=calculateSingle(w,width,strHeight,h);
}
// calculate only height
else if(height!=-1) {
width=calculateSingle(h,height,strWidth,w);
}
else {
width=procent2pixel(strWidth,w);
height=procent2pixel(strHeight,h);
if(width!=-1 && height!=-1) {}
else if(width==-1 && height==-1) {
width=w;
height=h;
}
else if(width!=-1)
height=calucalteFromOther(h,w,width);
else
width=calucalteFromOther(w,h,height);
}
sizes.put(key, rtn=new int[]{width,height});
return rtn;
}
private static int procent2pixel(String str, int source) throws ExpressionException {
if(!StringUtil.isEmpty(str)) {
if(StringUtil.endsWith(str, '%')) {
str=str.substring(0,str.length()-1).trim();
double procent = Caster.toDoubleValue(str);
if(procent<0 )
throw new ExpressionException("procent has to be positive number (now "+str+")");
return (int)(source*(procent/100D));
}
return Caster.toIntValue(str);
}
return -1;
}
private static int calculateSingle(int srcOther,int destOther, String strDim, int srcDim) throws ExpressionException {
int res = procent2pixel(strDim, srcDim);
if(res!=-1) return res;
return calucalteFromOther(srcDim,srcOther,destOther);//(int)(Caster.toDoubleValue(srcDim)*Caster.toDoubleValue(destOther)/Caster.toDoubleValue(srcOther));
}
private static int calucalteFromOther(int srcDim,int srcOther,int destOther) {
return (int)(Caster.toDoubleValue(srcDim)*Caster.toDoubleValue(destOther)/Caster.toDoubleValue(srcOther));
}
private static void checkResource(Resource resource) throws ApplicationException {
if(resource instanceof FileResource)return;
if(resource instanceof HTTPResource)
throw new ApplicationException("attribute width and height are required when external sources are invoked");
throw new ApplicationException("the resource type ["+resource.getResourceProvider().getScheme()+"] is not supported");
}
}