Larry Bouthillier's Streaming Media Player Detection Tutorial - server-side Java code

Listing One - PlayerDataObject.java

001 import java.lang.*; 002 import java.util.Hashtable; 003 import QTDataObject; 004 import RamDataObject; 005 import AsxDataObject; 006 007 public class PlayerDataObject{ 008 009 private static Hashtable cPlayerTypes; 010 public static String REAL_TYPE = "Real", RealClass="RamDataObject"; 011 public static String WMP_TYPE = "WMP", WMClass="AsxDataObject"; 012 public static String QT_TYPE = "QT", QTClass="QTDataObject"; 013 014 static { 015 cPlayerTypes=new Hashtable(); 016 cPlayerTypes.put(REAL_TYPE, RealClass); 017 cPlayerTypes.put(WMP_TYPE, WMClass); 018 cPlayerTypes.put(QT_TYPE, QTClass); 019 } 020 021 /** 022 * This method returns the correct subclass of PlayerDataObject for 023 * the PlayerType passed in. The PlayerType-to-ClassNames mapping is done in 024 * a static Hashtable in this class. In a "real' implementation we'd 025 * get this from a database or at least a properties file, rather than 026 * compiling it into a class. 027 * */ 028 public static PlayerDataObject getPlayerDataObject(String pPlayerType){ 029 PlayerDataObject mDataObject = null; 030 String mDataObjectName = (String) cPlayerTypes.get(pPlayerType); 031 System.out.println("PLAYERDATAOBJECT: getPlayerMetadataObject() read "+pPlayerType+" and is going to try to make a "+mDataObjectName); 032 try{ 033 if(mDataObjectName != null) { 034 mDataObject = (PlayerDataObject)Class.forName(mDataObjectName).newInstance(); 035 } 036 037 if ( mDataObject!=null ) { 038 System.out.println("PLAYERDATAOBJECT: getPlayerMetadataObject() read "+pPlayerType+" and created a "+ mDataObject.getClass().getName()); 039 return mDataObject; 040 } 041 }catch(ClassNotFoundException cnf){ 042 System.out.println("PLAYERDATAOBJECT: read "+pPlayerType+" and could not load PlayerDataObject subclass: "+ mDataObjectName +": " + cnf.getMessage());cnf.printStackTrace(); 043 } 044 catch(InstantiationException ie){System.out.println("Could not Instantiate (InstantiationException) PlayerDataObject subclass: "+ mDataObjectName);} 045 catch(IllegalAccessException iae){System.out.println("Could not Access (IllegalAccessException) PlayerDataObject subclass: "+ mDataObjectName);} 046 System.out.println("PLAYERDATAOBJECT: getPlayerDataObject() returning an empty class"); 047 return new PlayerDataObject(); 048 } 049 050 protected String cClipname=""; 051 public void setClipname(String s){ 052 cClipname = s; 053 } 054 public String getClipname(){ 055 return cClipname; 056 } 057 058 /** 059 * These values should be overridden by descendant classes 060 * */ 061 protected String PLUGIN_MIMETYPE=null; 062 protected String PLAYER_MIMETYPE=null; 063 public String getMimetype(){ 064 if ( cUsePluginMimetype == true ) { 065 return PLUGIN_MIMETYPE; 066 }else{ 067 return PLAYER_MIMETYPE; 068 } 069 } 070 071 protected boolean cUsePluginMimetype = false; 072 public void setUsePluginMimetype(boolean b){ 073 cUsePluginMimetype = b; 074 } 075 public boolean getUsePluginMimetype(){ 076 return cUsePluginMimetype; 077 } 078 079 080 /** 081 * Descendant classes should override this method to 082 * generate the appropriate player metafile for that 083 * player type (i.e. ram file, asx file, etc). 084 * Returns a fully qualified metafile to redirect to 085 * the requesting browser 086 * --------------------------------------------------*/ 087 public String play(){ 088 return null; 089 } 090 091 }

Listing Two - RamDataObject.java

001 public class RamDataObject extends PlayerDataObject{ 002 003 public RamDataObject(){ 004 PLAYER_MIMETYPE="audio/x-pn-realaudio"; 005 PLUGIN_MIMETYPE="audio/x-pn-realaudio-plugin"; 006 } 007 008 private String theServer = "maaz.hbs.edu"; 009 private String thePath = "/real_svt/"; 010 011 public String play(){ 012 String ramString = ""; 013 ramString = "rtsp://"+theServer +thePath + cClipname+".rm"; 014 return ramString; 015 } 016 }

Listing Three - QTDataObject.java

001 public class QTDataObject extends PlayerDataObject{ 002 003 public QTDataObject(){ 004 PLAYER_MIMETYPE="video/quicktime"; 005 PLUGIN_MIMETYPE="video/quicktime"; 006 } 007 008 private String theProtocol = "rtsp://"; 009 private String theServer = "maaz.hbs.edu"; 010 private String thePath = "/"; 011 012 public String play(){ 013 String smiString = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\" ?>\n<?quicktime type=\"application/smil\" ?>\n<!DOCTYPE smil PUBLIC \"-//W3C//DTD SMIL 1.0//EN\" \"http://www.w3c.org/TR/REC-smil/SMIL10.dtd\">\n"; 014 smiString += "<smil><body>"; 015 smiString += "<video src=\""+theProtocol + theServer +thePath + cClipname+".mov\" type=\"video/quicktime\"/>"; 016 smiString += "</body></smil>"; 017 return smiString; 018 } 019 }

Listing Four - AsxDataObject.java

001 public class AsxDataObject extends PlayerDataObject{ 002 003 public AsxDataObject(){ 004 PLAYER_MIMETYPE="video/x-ms-wmp"; 005 //PLAYER_MIMETYPE="text/plain"; 006 PLUGIN_MIMETYPE="video/x-ms-wm"; 007 } 008 009 private String theProtocol = "mms://"; 010 private String theServer = "hbs12-109.hbs.edu"; 011 private String thePath = "/"; 012 013 public String play(){ 014 String asxString = "<ASX Version=\"2\">\n"; 015 asxString+="<Entry>\n "; 016 //asxString+="<title>"+clip_win_title+"</title>\n"; 017 asxString+="<ref href=\""+theProtocol+theServer+thePath+cClipname+".wmv\"/>\n"; 018 // have to calculate the difference between clip_start and clip_end to get this 019 //s+="<Duration value=\""++"\"/> \n"; 020 asxString+="</Entry> \n"; 021 asxString+="</ASX> "; 022 return asxString; 023 } 024 }