blob: 24627f2099a0cb4c59528c01a2740422ee58c9f9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.myfaces.trinidadinternal.renderkit.core.xhtml;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.bean.PropertyKey;
import org.apache.myfaces.trinidad.component.core.output.CoreMedia;
import org.apache.myfaces.trinidad.context.RenderingContext;
import org.apache.myfaces.trinidad.util.IntegerUtils;
import org.apache.myfaces.trinidadinternal.agent.TrinidadAgent;
/**
* Base class for audio and video rendering.
*
* @version $Name: $ ($Revision: adfrt/faces/adf-faces-impl/src/main/java/oracle/adfinternal/view/faces/ui/laf/base/xhtml/MediaRenderer.java#0 $) $Date: 15-nov-2005.19:26:37 $
*/
public class MediaRenderer extends XhtmlRenderer
{
public MediaRenderer()
{
super(CoreMedia.TYPE);
}
@Override
protected void findTypeConstants(
FacesBean.Type type)
{
super.findTypeConstants(type);
_sourceKey = type.findKey("source");
_playerKey = type.findKey("player");
_contentTypeKey = type.findKey("contentType");
_autostartKey = type.findKey("autostart");
_playCountKey = type.findKey("playCount");
_controlsKey = type.findKey("controls");
_standbyTextKey = type.findKey("standbyText");
_widthKey = type.findKey("width");
_heightKey = type.findKey("height");
_innerWidthKey = type.findKey("innerWidth");
_innerHeightKey = type.findKey("innerHeight");
}
protected String getSource(
UIComponent component,
FacesBean bean)
{
return toResourceUri(FacesContext.getCurrentInstance(), bean.getProperty(_sourceKey));
}
protected String getPlayer(
UIComponent component,
FacesBean bean)
{
return toString(bean.getProperty(_playerKey));
}
protected String getContentType(
UIComponent component,
FacesBean bean)
{
return toString(bean.getProperty(_contentTypeKey));
}
protected String getControls(
UIComponent component,
FacesBean bean)
{
return toString(bean.getProperty(_controlsKey));
}
protected String getStandbyText(
UIComponent component,
FacesBean bean)
{
return toString(bean.getProperty(_standbyTextKey));
}
protected boolean getAutostart(
UIComponent component,
FacesBean bean)
{
Object o = bean.getProperty(_autostartKey);
if (o == null)
o = _autostartKey.getDefault();
return Boolean.TRUE.equals(o);
}
protected Number getPlayCount(
UIComponent component,
FacesBean bean)
{
Object o = bean.getProperty(_playCountKey);
if (o == null)
o = _playCountKey.getDefault();
if (o instanceof Number)
return ((Number) o);
return null;
}
protected String getWidth(
UIComponent component,
FacesBean bean)
{
return toString(bean.getProperty(_widthKey));
}
protected String getHeight(
UIComponent component,
FacesBean bean)
{
return toString(bean.getProperty(_heightKey));
}
protected String getInnerWidth(
UIComponent component,
FacesBean bean)
{
return toString(bean.getProperty(_innerWidthKey));
}
protected String getInnerHeight(
UIComponent component,
FacesBean bean)
{
return toString(bean.getProperty(_innerHeightKey));
}
@Override
public boolean getRendersChildren()
{
return true;
}
@Override
protected void encodeAll(
FacesContext context,
RenderingContext rc,
UIComponent component,
FacesBean bean
) throws IOException
{
if (canSkipRendering(context, rc, component))
return;
// get the mime type
String mimeType = _getMimeType(component, bean);
// extract the primary cotnent type from the content mime type
String primaryContentType = _getPrimaryContentType(mimeType);
MediaRenderer.PlayerData playerData = _getPlayerData(rc, component, bean, mimeType,
primaryContentType);
ResponseWriter writer = context.getResponseWriter();
String source = getSource(component, bean);
String contentType = getContentType(component, bean);
String id = getClientId(context, component);
if (_LINK_PLAYER_DATA == playerData)
{
_renderLink(context,
rc,
component,
bean,
id,
source,
null,
contentType);
}
else
{
// determine which controls to display based on the primary
// mime type
MediaRenderer.ControlSet controlSet = playerData.getControlSet(primaryContentType);
MediaRenderer.ControlData imageWindowControlData =
playerData.getImageWindowControlData(primaryContentType);
MediaRenderer.ControlData controlData = (controlSet != null)
? controlSet.getControlData(
getControls(component, bean))
: null;
//
// Determine which tags to use
//
boolean useEmbedTag = true;
boolean useObjectTag = true;
boolean isImage = _IMAGE_PLAYER_DATA == playerData;
if (isImage)
{
useEmbedTag = false;
useObjectTag = false;
}
else
{
useEmbedTag = useEmbed(rc);
useObjectTag = !useEmbedTag;
}
String width = getWidth(component, bean);
// since current players don't add to width, treat innerWidth
// identically to width for now
if (width == null)
width = getInnerWidth(component, bean);
// get whether this set of controls can be autosized.
// embed elements can not be autosized.
boolean canAutosize = playerData.canAlwaysAutosize ||
(controlData.canAutosize && !useEmbedTag);
// compute default width for players that don't autosize
if ((width == null) && !canAutosize)
{
Number defaultInnerWidth = getDefaultInnerWidth(primaryContentType);
// use the greater of the default width of the content
// and the preferred width of the controls
width = ((defaultInnerWidth.intValue() >
controlData.preferredWidth.intValue())
? defaultInnerWidth
: controlData.preferredWidth).toString();
}
// default the autostarting value
String autostartValue = null;
// default the playcount param name and value
String playCountParamName = null;
Object playCountParamValue = null;
if (!isImage)
{
//
// Handle looping attributes
//
Number playCountValue = getPlayCount(component, bean);
if (playCountValue != null)
{
int playCount = playCountValue.intValue();
if ((playCount != 1) && (playCount >= 0))
{
if (playCount == 0)
{
// some players handle infinite looping specially
playCountParamName = playerData.infiniteLoopParamName;
playCountParamValue = playerData.infiniteLoopParamValue;
}
else
{
playCountParamName = playerData.playCountParamName;
playCountParamValue = playCountValue;
}
}
}
//
// determine whether we should autostart
//
boolean autostarts = getAutostart(component, bean);
if (autostarts != playerData.autostartByDefault)
{
// only write out an autostart value, if its different than
// the default
autostartValue = autostarts
? playerData.autostartTrueValue
: playerData.autostartFalseValue;
}
}
String standbyText = getStandbyText(component, bean);
String height = null;
// if image window and controls rendered separately
if ( imageWindowControlData != null )
{
height = _getInnerHeight(component, bean, canAutosize, primaryContentType, controlData,
playerData);
// since image and controls are rendered separately, a value
// is needed to associate them. The id will be used if it is not null,
// otherwise an id will be generated for the value.
String wireImageToControlsParamValue = id;
_render( context,
rc,
component,
bean,
contentType,
id,
wireImageToControlsParamValue,
source,
standbyText,
width,
height,
autostartValue,
playCountParamName,
playCountParamValue,
playerData,
imageWindowControlData,
useEmbedTag,
useObjectTag,
isImage,
false);
if ( controlData != _NULL_CONTROL_DATA )
{
writer.startElement("div", component);
writer.endElement("div");
height = IntegerUtils.getString(controlData.height);
_render( context,
rc,
component,
bean,
contentType,
id,
wireImageToControlsParamValue,
null,
null,
width,
height,
null,
null,
null,
playerData,
controlData,
useEmbedTag,
useObjectTag,
isImage,
true);
}
}
// if image window and controls rendered together
else
{
height = _getHeight(component, bean, canAutosize, primaryContentType, controlData,
playerData);
_render( context,
rc,
component,
bean,
contentType,
id,
null,
source,
standbyText,
width,
height,
autostartValue,
playCountParamName,
playCountParamValue,
playerData,
controlData,
useEmbedTag,
useObjectTag,
isImage,
false);
}
if (useEmbedTag)
{
//
// render the alternative link content
//
// =-=bts I feel that our backup rendering should be an icon that
// we retrieve using a pretected method
//
writer.startElement("noembed", component);
_renderLink(context, rc, component, bean, null, source, null, contentType);
writer.endElement("noembed");
}
}
}
/**
* Returns the default inner width to use for players when no width is
* specified.
*/
protected Number getDefaultInnerWidth(
String primaryContentType
)
{
return _getDefaultSizeArray(primaryContentType)[_DEFAULT_INNER_WIDTH_INDEX];
}
/**
* Returns the default inner height to use for players when no height is
* specified.
*/
protected Number getDefaultInnerHeight(
String primaryContentType
)
{
return _getDefaultSizeArray(primaryContentType)[_DEFAULT_INNER_HEIGHT_INDEX];
}
/**
* Returns true if we should use the <embed> tag instead of the
* <object> tag to embed the viewer
*/
protected boolean useEmbed(
RenderingContext rc
)
{
TrinidadAgent agent = (TrinidadAgent) rc.getAgent();
// =-= bts only desktop IE seems to support this
// Move this to capability
return !((agent.getAgentType() == TrinidadAgent.TYPE_DESKTOP) &&
(agent.getAgentApplication() == TrinidadAgent.Application.IEXPLORER) &&
(agent.getAgentOS() == TrinidadAgent.OS_WINDOWS));
}
private Number[] _getDefaultSizeArray(
String primaryContentType
)
{
Object sizeArray = _sDefaultInnerSizes.get(primaryContentType);
if (sizeArray == null)
{
// try again with video if no entry found for this primary content type
sizeArray = _sDefaultInnerSizes.get("video");
}
return (Number[])sizeArray;
}
/**
* Renders a link
*/
private void _renderLink(
FacesContext context,
RenderingContext rc,
UIComponent component,
FacesBean bean,
String id,
String source,
String iconUrl,
String contentType
) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
// Don't render a link without an "href".
// But, for PPR, always render a span if we have an ID.
if (source == null)
{
if (id != null)
{
writer.startElement("span", null);
writer.writeAttribute("id", id, null);
renderAllAttributes(context, rc, component, bean);
writer.endElement("span");
}
}
else
{
writer.startElement("a", component);
// write the ID
if (id != null)
{
writer.writeAttribute("id", id, null);
// And render all the attributes here if we have
// that ID, because that means this is the main
// content
renderAllAttributes(context, rc, component, bean);
}
// link to the content
renderEncodedActionURI(context, "href", source);
// mime-type of content
writer.writeAttribute("type", contentType, null);
if (iconUrl != null)
{
// =-=AEW Just noticed: this code fails to render "alt"; before
// using, check accessibility!!!
writer.startElement("img", null);
renderEncodedResourceURI(context, "src", iconUrl);
writer.endElement("img");
}
String shortDesc = getShortDesc(component, bean);
if (shortDesc != null)
writer.writeText(shortDesc, "shortDesc");
writer.endElement("a");
}
}
/**
* Renders a name value pair as a <param> element
*/
private void _renderParamAttribute(
FacesContext context,
String paramName,
Object paramValue,
boolean isURL
) throws IOException
{
if ( paramValue != null )
{
ResponseWriter writer = context.getResponseWriter();
writer.startElement("param", null);
writer.writeAttribute("name", paramName, null);
if (isURL)
{
renderEncodedResourceURI(context, "value", paramValue);
}
else
{
writer.writeAttribute("value", paramValue, null);
}
writer.endElement("param");
}
}
/**
* Returns the constant identifying the player to use
*
* =-= bts Do we care about AccessibilityMode?
*/
private MediaRenderer.PlayerData _getPlayerData(
RenderingContext rc,
UIComponent component,
FacesBean bean,
String mimeType,
String primaryMimeType
)
{
PlayerData playerData = null;
// the default player is the link player
TrinidadAgent agent = (TrinidadAgent) rc.getAgent();
int agentOSInt = agent.getAgentOS();
// get the set of supported players for this OS
HashSet<Object> supportedPlayers = _sSupportedOSPlayers.get(agentOSInt);
// are we trying to display an image?
boolean isImage = "image".equals(primaryMimeType);
// check if this OS supports any non-link style players
if (supportedPlayers != null)
{
// get the desired player, if any
String playerString = getPlayer(component, bean);
if (playerString != null)
{
if (CoreMedia.PLAYER_LINK.equals(playerString))
{
playerData = _LINK_PLAYER_DATA;
}
else
{
// check that the specified player is supported
if (!isImage && supportedPlayers.contains(playerString))
{
playerData = (PlayerData) _sPlayerData.get(playerString);
if (playerData != null)
{
if (mimeType != null)
{
// check that the format is supported by this player
if (!playerData.isSupportedMimeType(mimeType))
{
playerData = null;
}
}
}
}
}
}
// assume that all images can be played by the browser's built-in
// image player
if (isImage)
playerData = _IMAGE_PLAYER_DATA;
else
{
// if the primary content type isn't image, video, or audio,
// use the link player
if (!"video".equals(primaryMimeType) &&
!"audio".equals(primaryMimeType))
playerData = _LINK_PLAYER_DATA;
}
//
// guess the player based on the mime type
//
if (playerData == null)
{
Object preferredPlayer = _sPreferredMimePlayers.get(mimeType);
if ((preferredPlayer != null) &&
supportedPlayers.contains(preferredPlayer))
{
playerData = (PlayerData) _sPlayerData.get(preferredPlayer);
}
}
//
// guess the player based on the operating system
//
if (playerData == null)
{
Object preferredPlayer = _sPreferredOSPlayers.get(agentOSInt);
if (preferredPlayer != null)
{
playerData = (PlayerData) _sPlayerData.get(preferredPlayer);
// check that the format is supported by this player
if (!playerData.isSupportedMimeType(mimeType))
{
playerData = null;
}
}
}
}
// if all else fails, use the link player
if (playerData == null)
playerData = _LINK_PLAYER_DATA;
return playerData;
}
/**
* Returns the primary content type of the result:
* i.e. "audio", "video"
*/
private String _getPrimaryContentType(
String mimeType
)
{
if (mimeType != null)
{
int slashIndex = mimeType.indexOf('/');
if (slashIndex != -1)
{
return mimeType.substring(0, slashIndex);
}
}
return null;
}
/**
* Returns the secondary content type of the result:
* i.e. "quicktime", "au"
*/
private String _getSecondaryContentType(
String mimeType
)
{
if (mimeType != null)
{
int slashIndex = mimeType.indexOf('/');
if (slashIndex != -1)
{
return mimeType.substring(slashIndex + 1);
}
}
return null;
}
/**
* Returns the most likely MIME type for the content
*/
private String _getMimeType(
UIComponent component,
FacesBean bean)
{
// try any provided content mime type first
String mimeType = getContentType(component, bean);
// primary mime type to force mime type to
String primaryForced = null;
if (mimeType != null)
{
// convert mime types to lower case
mimeType = mimeType.toLowerCase(Locale.US);
// Check that the user hasn't forced the primary mime-type
int mimeLength = mimeType.length();
if ((mimeType.charAt(mimeLength - 1) == '*') &&
(mimeType.charAt(mimeLength - 2) == '/'))
{
// force the primary mime type
primaryForced = mimeType.substring(0, mimeLength - 2);
}
else
{
Object remapped = _sMimeTypeRemapper.get(mimeType);
if (remapped != null)
{
// we remapped the in mime-type to the cannonical mime type
return remapped.toString();
}
else
{
// return the mime-type as is
return mimeType;
}
}
}
// try to determine the mime-type off of the source extension
String extension = _getSourceExtension(component, bean);
if (extension != null)
{
// try to map the extension to a mime type
Object mimeTypeObject = _sExtensionMap.get(extension);
if (mimeTypeObject != null)
{
mimeType = mimeTypeObject.toString();
if (primaryForced != null)
{
// merge the primary forced type with the extension mapped secondary
// type
mimeType = primaryForced + '/' + _getSecondaryContentType(mimeType);
}
}
}
return mimeType;
}
/**
* Returns the lowercase extension of any source URL
*/
private String _getSourceExtension(
UIComponent component,
FacesBean bean)
{
String sourceURLString = getSource(component, bean);
if (sourceURLString != null)
{
int extensionIndex = sourceURLString.lastIndexOf('.');
if ((extensionIndex != -1) &&
(extensionIndex != sourceURLString.length() -1))
{
return sourceURLString.substring(extensionIndex + 1).toLowerCase();
}
}
// no extension
return null;
}
/**
* Initializes a Hashset with the contents of an array
*/
private static HashSet<Object> _createHashSet(
Object[] contents
)
{
if (contents != null)
{
int contentLength = contents.length;
HashSet<Object> set =
new HashSet<Object>((int)(contentLength * 1.5));
for (int i = 0; i < contentLength; i++)
{
set.add(contents[i]);
}
return set;
}
else
{
return null;
}
}
/**
* Initializes a HashMap with the name/value contents of an array
*/
private static HashMap<Object, Object> _createHashMap(
Object[] contents
)
{
if (contents != null)
{
int contentLength = contents.length;
HashMap<Object, Object> map =
new HashMap<Object, Object>((int)(contentLength * 0.75));
for (int i = 0; i < contentLength; i += 2)
{
map.put(contents[i], contents[i + 1]);
}
return map;
}
else
{
return null;
}
}
// get the height of the image window
private String _getInnerHeight(
UIComponent component,
FacesBean bean,
boolean canAutosize,
String primaryContentType,
ControlData controlData,
PlayerData playerData
)
{
// get the height without checking min
String height = _getHeightNoMin(component, bean, canAutosize, primaryContentType, controlData);
boolean useMinHeight = (height == null);
if (!useMinHeight)
{
int intHeight = _getIntHeight(height);
// - if intHeight equals Integer.MAX_VALUE then height could not be
// turned to an int, return height
// - if intHeight is less than playerData.minHeight.intValue()
// then return player min - contorl data height if possible
// - if intHeight is between the player min and Integer.MAX_VALUE
// then return inHeight - control data height
if (playerData.minHeight != null &&
intHeight < playerData.minHeight.intValue())
{
useMinHeight = true;
}
else if ( intHeight < Integer.MAX_VALUE )
{
return IntegerUtils.getString(intHeight - controlData.height);
}
}
if (useMinHeight)
{
return IntegerUtils.getString(playerData.minHeight.intValue() -
controlData.height);
}
return height;
}
//
// determine the height without checking the min height
//
private String _getHeightNoMin(
UIComponent component,
FacesBean bean,
boolean canAutosize,
String primaryContentType,
ControlData controlData
)
{
String height = getHeight(component, bean);
// compute default height for players that don't autosize
if (height == null)
{
// get the inner height from the attribute
String innerHeight = getInnerHeight(component, bean);
if (!canAutosize && (innerHeight == null))
{
// get the default inner height
innerHeight = getDefaultInnerHeight(primaryContentType).toString();
}
//
// convert from inner height to outer height
//
int extraHeight = (controlData != null)
? controlData.height
: 0;
if ((innerHeight != null) && (extraHeight != 0))
{
try
{
int innerHeightInt = Integer.parseInt(innerHeight);
height = Integer.toString(innerHeightInt + extraHeight);
}
catch (NumberFormatException nfe)
{
height = innerHeight;
}
}
else
{
height = innerHeight;
}
}
return height;
}
//
// determine the height including the controls
//
private String _getHeight(
UIComponent component,
FacesBean bean,
boolean canAutosize,
String primaryContentType,
ControlData controlData,
PlayerData playerData
)
{
// get the height
String height = _getHeightNoMin(component, bean, canAutosize, primaryContentType, controlData);
//
// apply minimum player size to height
//
if (playerData.minHeight != null)
{
boolean useMinHeight = (height == null);
if (!useMinHeight)
{
int intHeight = _getIntHeight(height);
useMinHeight = (playerData.minHeight.intValue() > intHeight);
}
if (useMinHeight)
{
height = playerData.minHeight.toString();
}
}
return height;
}
// try to transform height to an int
// returns Integer.MAX_VALUE if unable to transform height to an int
private int _getIntHeight(
Object height
)
{
int intHeight;
if (height instanceof Number)
{
intHeight = ((Number)height).intValue();
}
else
{
String stringHeight = height.toString();
// don't parse 0.000000e+000ights
if (stringHeight.indexOf('%') == -1)
{
try
{
intHeight = new Integer(stringHeight).intValue();
}
catch (NumberFormatException e)
{
// not a number
intHeight = Integer.MAX_VALUE;
}
}
else
{
intHeight = Integer.MAX_VALUE;
}
}
return intHeight;
}
private void _render(
FacesContext context,
RenderingContext rc,
UIComponent component,
FacesBean bean,
String contentType,
String id,
String wireImageToControls,
String source,
String standbyText,
String width,
String height,
String autostartValue,
String playCountParamName,
Object playCountParamValue,
PlayerData playerData,
ControlData controlData,
boolean useEmbedTag,
boolean useObjectTag,
boolean isImage,
boolean isNotMainID
) throws IOException
{
String elementName = (isImage)
? "img"
: (useEmbedTag)
? "embed"
: "object";
// name of attribute to use to write out source URL
String sourceAttrName = "src";
ResponseWriter writer = context.getResponseWriter();
// start the element
writer.startElement(elementName, component);
renderAllAttributes(context, rc, component, bean);
writer.writeAttribute("width", width, null);
writer.writeAttribute("height", height, null);
if (!isImage)
{
//
// <embed> uses direct attributes
//
if (useEmbedTag)
{
// embed doesn't support id, use name instead
writer.writeAttribute("name", id, null );
// =-= bts, we might only want to do this if the client has specified
// that they want this particular player
writer.writeAttribute("type", playerData.playerMimeType, null);
// location to download new plug-in from
writer.writeAttribute("pluginspage", playerData.pluginsPage, null);
// autostart
writer.writeAttribute(playerData.autostartParamName, autostartValue, null);
// looping
writer.writeAttribute(playCountParamName, playCountParamValue, null);
// wire image window to controls
writer.writeAttribute(playerData.wireImageToControlsParamName,
wireImageToControls,
null);
// add in control attributes
if (controlData != null)
{
String[] paramNameValues = controlData.paramNameValues;
if (paramNameValues != null)
{
for (int i = 0; i < paramNameValues.length; i += 2)
{
writer.writeAttribute(paramNameValues[i], paramNameValues[i+1], null);
}
}
}
}
else
{
if (!isNotMainID )
writer.writeAttribute("id", id, null);
// Object tag doesn't take a source attribute
sourceAttrName = null;
// override the content type with a player-specified type
// =-= bts What does this do?
if (playerData.overrideContentType != null)
{
contentType = playerData.overrideContentType;
}
// =-= bts maybe we should have a default message
writer.writeAttribute("standby", standbyText, null);
// mime-type of content
writer.writeAttribute("type", contentType, null);
// Class ID
writer.writeAttribute("classid", playerData.classID, null);
// Download location
writer.writeAttribute("codebase", playerData.codeBase, null);
}
}
// write out the source if any
if (sourceAttrName != null)
{
renderEncodedResourceURI(context, sourceAttrName, source);
}
//
// write out Object tag content
//
if (useObjectTag)
{
//
// render the parameters to the player
//
// source of content
_renderParamAttribute(context,
playerData.sourceParamName,
source,
true);
// autostart
_renderParamAttribute(context,
playerData.autostartParamName,
autostartValue,
false);
// looping
_renderParamAttribute(context,
playCountParamName,
playCountParamValue,
false);
// wire image window to controls
if ( playerData.wireImageToControlsParamName != null )
{
_renderParamAttribute(context,
playerData.wireImageToControlsParamName,
wireImageToControls,
false);
}
// add in control attributes
if (controlData != null )
{
String[] paramNameValues = controlData.paramNameValues;
if (paramNameValues != null)
{
for (int i = 0; i < paramNameValues.length; i += 2)
{
_renderParamAttribute(context,
paramNameValues[i],
paramNameValues[i + 1],
false);
}
}
}
//
// render the link as alternative content
//
// =-=bts I feel that our backup rendering should be an icon that
// we retrieve using a pretected method
//
_renderLink(context, rc, component, bean, null, source, null, contentType);
}
// close the element
writer.endElement(elementName);
}
//
// known mime types
//
private static final String _AIFF_MIME_TYPE = "audio/aiff";
private static final String _ART_MIME_TYPE = "image/x-art";
private static final String _ASF_MIME_TYPE = "video/x-ms-asf";
private static final String _AVI_MIME_TYPE = "video/avi";
private static final String _BMP_MIME_TYPE = "image/bmp";
private static final String _GIF_MIME_TYPE = "image/gif";
private static final String _HTML_MIME_TYPE = "text/html";
private static final String _IEF_IMAGE_MIME_TYPE = "image/ief";
private static final String _JPEG_MIME_TYPE = "image/jpeg";
private static final String _MIDI_MIME_TYPE = "audio/mid";
private static final String _MPEG_AUDIO_MIME_TYPE = "audio/mpeg";
private static final String _MPEG_VIDEO_MIME_TYPE = "video/mpeg";
private static final String _MPEG2_VIDEO_MIME_TYPE = "video/x-mpeg2";
private static final String _PLAIN_TEXT_MIME_TYPE = "text/plain";
private static final String _PORTABLE_ANYMAP_MIME_TYPE = "image/x-portable-anymap";
private static final String _PORTABLE_BITMAP_MIME_TYPE = "image/x-portable-bitmap";
private static final String _PORTABLE_GRAYMAP_MIME_TYPE = "image/x-portable-graymap";
private static final String _PICT_MIME_TYPE = "image/pict";
private static final String _PNG_MIME_TYPE = "image/png";
private static final String _QUICKTIME_MIME_TYPE = "video/quicktime";
private static final String _CMU_RASTER_MIME_TYPE = "image/x-cmu-raster";
private static final String _REAL_AUDIO_MIME_TYPE = "audio/x-realaudio";
private static final String _REAL_AUDIO_PLUGIN_MIME_TYPE = "audio/x-pn-realaudio-plugin";
private static final String _REAL_AUDIO_PN_MIME_TYPE = "audio/x-pn-realaudio";
private static final String _REAL_VIDEO_MIME_TYPE = "video/x-realaudio";
private static final String _REAL_VIDEO_PLUGIN_MIME_TYPE = "video/x-pn-realaudio-plugin";
private static final String _REAL_VIDEO_PN_MIME_TYPE = "video/x-pn-realaudio";
private static final String _RGB_MIME_TYPE = "image/x-rgb";
private static final String _SGI_MOVIE_MIME_TYPE = "video/x-sgi-movie";
private static final String _SMIL_MIME_TYPE = "application/smil";
private static final String _TIFF_MIME_TYPE = "image/tiff";
private static final String _ULAW_MIME_TYPE = "audio/basic";
private static final String _WAV_MIME_TYPE = "audio/wav";
private static final String _WMA_MIME_TYPE = "audio/x-ms-wma";
private static final String _WMV_MIME_TYPE = "video/x-ms-wmv";
private static final String _WVX_MIME_TYPE = "video/x-ms-wvx";
private static final String _X_BITMAP_MIME_TYPE = "image/x-xbitmap";
private static final String _X_PIXMAP_MIME_TYPE = "image/x-xpixmap";
private static final String _X_WINDOW_DUMP_MIME_TYPE = "image/x-xwindowdump";
// Maps MIME type variants to the cannonical MIME type
private static final String[] _MIME_TYPE_REMAPPER = new String[]
{
"audio/vnd.rn-realaudio", _REAL_AUDIO_PN_MIME_TYPE,
"video/vnd.rn-realvideo", _REAL_VIDEO_PN_MIME_TYPE,
"audio/x-aiff", _AIFF_MIME_TYPE,
"audio/x-mpeg", _MPEG_AUDIO_MIME_TYPE,
"audio/x-wav", _WAV_MIME_TYPE,
"video/msvideo", _AVI_MIME_TYPE,
"video/x-mpeg", _MPEG_VIDEO_MIME_TYPE,
"video/x-msvideo", _AVI_MIME_TYPE,
};
/**
* Maintains attribute and size information for a particular control
* configuration.
*/
private static class ControlData
{
public ControlData(
String[] paramNameValues,
boolean canAutosize,
int height,
Number preferredWidth
)
{
if (height < 0)
throw new IllegalArgumentException();
if (preferredWidth.intValue() < 0)
throw new IllegalArgumentException();
this.paramNameValues = paramNameValues;
this.canAutosize = canAutosize;
this.height = height;
this.preferredWidth = preferredWidth;
}
// name values necessary to get to this control state
public String[] paramNameValues;
public boolean canAutosize;
public int height;
public Number preferredWidth;
}
/**
* Maintains default innersize information and ControlData information
* for a set of ControlData's for a primary content type
*/
private static class ControlSet
{
public ControlSet(
Object[] controls
)
{
_controls = _createHashMap(controls);
}
/**
* Returns the ControlData Object to use to build up the set of controls
* for this player, based on the client-specified set of controls to render.
*/
public MediaRenderer.ControlData getControlData(
Object controlValue
)
{
Object controlData = null;
// get the specified control data
if (controlValue != null)
{
controlData = _controls.get(controlValue.toString());
}
// if we failed for some reason, default to the typical controls
if (controlData == null)
{
controlData = _controls.get(CoreMedia.CONTROLS_TYPICAL);
}
return (ControlData)controlData;
}
private final HashMap<Object, Object> _controls;
}
/**
* Class containing information about the different players
*/
private static class PlayerData
{
public PlayerData(
String player,
boolean autostartByDefault,
String autostartTrueValue,
String autostartFalseValue,
boolean canAlwaysAutosize,
Number minHeight,
String autostartParamName,
String sourceParamName,
String infiniteLoopParamName,
Object infiniteLoopParamValue,
String playCountParamName,
String pluginsPage,
String codeBase,
String playerMimeType,
String classID,
String overrideContentType,
String wireImageToControlsParamName,
ControlData imageWindowControlData,
Object[] controlSets,
Object[] unsupportedMimeTypes
)
{
if ((minHeight != null) && (minHeight.intValue() < 0))
throw new IllegalArgumentException();
this.player = player;
this.autostartByDefault = autostartByDefault;
this.autostartTrueValue = autostartTrueValue;
this.autostartFalseValue = autostartFalseValue;
this.canAlwaysAutosize = canAlwaysAutosize;
this.minHeight = minHeight;
this.autostartParamName = autostartParamName;
this.sourceParamName = sourceParamName;
this.infiniteLoopParamName = infiniteLoopParamName;
this.infiniteLoopParamValue = infiniteLoopParamValue;
this.playCountParamName = playCountParamName;
this.pluginsPage = pluginsPage;
this.codeBase = codeBase;
this.classID = classID;
this.playerMimeType = playerMimeType;
this.overrideContentType = overrideContentType;
this.wireImageToControlsParamName = wireImageToControlsParamName;
_imageWindowControlData = imageWindowControlData;
_controlSets = _createHashMap(controlSets);
_unsupportedMimeTypes = _createHashSet(unsupportedMimeTypes);
}
public MediaRenderer.ControlData getImageWindowControlData(
String primaryContentType
)
{
if ( "video".equals(primaryContentType))
return _imageWindowControlData;
return null;
}
/**
* Returns the ControlSet Object to use to build up the set of controls
* for this player, based on the primary content MimeType
*/
public MediaRenderer.ControlSet getControlSet(
String primaryContentType
)
{
if (_controlSets != null)
{
Object controls = null;
// get the primary hashmap
if (primaryContentType != null)
controls = _controlSets.get(primaryContentType);
// if we have an unknown primary typoe, try again with video,
// which shouldn't fail
if (controls == null)
controls = _controlSets.get("video");
return (ControlSet)controls;
}
return null;
}
/**
* Returns true if the player supports rendering this format
*/
public boolean isSupportedMimeType(
String mimeType
)
{
if ((mimeType != null) && (mimeType.length() != 0))
{
if (_unsupportedMimeTypes != null)
{
// extension isn't listed as an unsupported extension
return !_unsupportedMimeTypes.contains(mimeType);
}
}
return true;
}
public final String player;
public final boolean autostartByDefault;
public final String autostartTrueValue;
public final String autostartFalseValue;
public final boolean canAlwaysAutosize;
public final Number minHeight;
public final String autostartParamName;
public final String sourceParamName;
public final String infiniteLoopParamName;
public final Object infiniteLoopParamValue;
public final String playCountParamName;
public final String pluginsPage;
public final String codeBase;
public final String playerMimeType;
public final String classID;
public final String overrideContentType;
public final String wireImageToControlsParamName;
private final ControlData _imageWindowControlData;
private final HashMap<Object, Object> _controlSets;
private final HashSet<Object> _unsupportedMimeTypes;
}
// Real Player Class ID
private static final String _RP_CLASS_ID =
"clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA";
// QuickTime class id
private static final String _QT_CLASS_ID =
"clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B";
private static final String _QT_CODE_BASE =
"http://www.apple.com/qtactivex/qtplugin.cab";
private static final String _WMP_6_4_CLASS_ID =
"clsid:22D6F312-B0F6-11D0-94AB-0080C74C7E95";
private static final String _WMP_CODE_BASE =
"http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,0,02,902";
private static final Integer _MIN_QT_HEIGHT = 2;
private static final int _QT_CONTROL_HEIGHT = 16;
private static final int _WMP_CONTROL_HEIGHT = 40;
//
// Meta Data for the Link Player
//
private static final MediaRenderer.PlayerData _LINK_PLAYER_DATA =
new MediaRenderer.PlayerData(CoreMedia.PLAYER_LINK, // player type
false, // no autostart by default
"true", // autostartTrueValue
"false", // autostartFalseValue
true, // can always autosize
null, // min player height
null, // autostartParamName
null, // sourceParamName
null, // infiniteLoopParamName,
null, // infiniteLoopParamValue
null, // playCountParamName
null, // pluginsPage URL
null, // <Object> CodeBase
null, // playerMimeType
null, // <Object> ClassID
null, // overrideContentType
null, // wireImageToControlsParamName
null, // imageWindowControlData
null, // ControlData[]
null); // Unsupported MimeTypes
//
//
private static final MediaRenderer.PlayerData _IMAGE_PLAYER_DATA =
new MediaRenderer.PlayerData("image", // player type
false, // no autostart by default
"true", // autostartTrueValue
"false", // autostartFalseValue
true, // can always autosize
null, // min player height
null, // autostartParamName
null, // sourceParamName
null, // infiniteLoopParamName,
null, // infiniteLoopParamValue
null, // playCountParamName
null, // pluginsPage URL
null, // <Object> CodeBase
null, // playerMimeType
null, // <Object> ClassID
null, // overrideContentType
null, // wireImageToControlsParamName
null, // imageWindowControlData
null, // ControlData[]
null); // Unsupported MimeTypes
//
// Meta Data for the Quicktime Player
//
// ControlData for the QuickTime all controls case
private static final MediaRenderer.ControlData _QUICKTIME_ALL_CONTROL_DATA =
new MediaRenderer.ControlData(null, // all controls is the default
false, // no autosize
_QT_CONTROL_HEIGHT, // extra height
Integer.valueOf(275)); // preferred width
private static final MediaRenderer.PlayerData _QUICKTIME_PLAYER_DATA =
new MediaRenderer.PlayerData(
CoreMedia.PLAYER_QUICKTIME, // player type
true, // autostart by default
"true", // autostartTrueValue
"false", // autostartFalseValue
false, // can't always autosize
_MIN_QT_HEIGHT, // min player height
"autoplay", // autostartParamName
"src", // sourceParamName
"loop", // infiniteLoopParamName,
"true", // infiniteLoopParamValue
null, // no loop count support
"http://www.apple.com/quicktime/download/", // pluginsPage
_QT_CODE_BASE, // <Object> CodeBase
null, // playerMimeType
_QT_CLASS_ID, // <Object> ClassID
null, // overrideContentType
null, // wireImageToControlsParamName
null, // imageWindowControlData
new Object[]
{
"audio", new MediaRenderer.ControlSet(new Object[]
{
CoreMedia.CONTROLS_NONE, new MediaRenderer.ControlData(new String[]
{
"kioskmode", "true",
"controller","false",
},
false, // no autosize
0,
0),
CoreMedia.CONTROLS_NONE_VISIBLE, new MediaRenderer.ControlData(new String[]
{
"controller", "false"
},
false, // no autosize
0,
0),
CoreMedia.CONTROLS_MINIMAL, new MediaRenderer.ControlData(null, // all controls default
false, // no autosize
_QT_CONTROL_HEIGHT,
Integer.valueOf(18)), // play button only
CoreMedia.CONTROLS_TYPICAL, _QUICKTIME_ALL_CONTROL_DATA,
CoreMedia.CONTROLS_ALL, _QUICKTIME_ALL_CONTROL_DATA,
}),
"video", new MediaRenderer.ControlSet(new Object[]
{
CoreMedia.CONTROLS_NONE, new MediaRenderer.ControlData(new String[]
{
"kioskmode", "true",
"controller","false",
},
false, // no autosize
0,
0),
CoreMedia.CONTROLS_NONE_VISIBLE, new MediaRenderer.ControlData(new String[]
{
"controller", "false"
},
false, // no autosize
0,
0),
CoreMedia.CONTROLS_MINIMAL, _QUICKTIME_ALL_CONTROL_DATA,
CoreMedia.CONTROLS_TYPICAL, _QUICKTIME_ALL_CONTROL_DATA,
CoreMedia.CONTROLS_ALL, _QUICKTIME_ALL_CONTROL_DATA,
}),
},
new String[] // mime-types not supported by Quicktime 5
{
_WMA_MIME_TYPE,
_WMV_MIME_TYPE,
_REAL_AUDIO_MIME_TYPE,
_REAL_AUDIO_PN_MIME_TYPE,
_REAL_AUDIO_PLUGIN_MIME_TYPE,
_REAL_VIDEO_MIME_TYPE,
_REAL_VIDEO_PN_MIME_TYPE,
_REAL_VIDEO_PLUGIN_MIME_TYPE,
});
//
// Meta Data for the Windows Media Player 6.4
//
// preferred width of WMP showing all controls
private static final Number _WMP_ALL_CONTROLS_WIDTH = Integer.valueOf(275);
private static final Number _WMP_MINIMAL_CONTROLS_WIDTH =
72;
private static final int _WMP_MINIMAL_CONTROLS_HEIGHT = 21;
private static final int _WMP_ALL_CONTROLS_HEIGHT = 170;
// control data for showing no visible controls on Windows Meida Player 6.4
private static final MediaRenderer.ControlData _WMP_6_4_NONE_VISIBLE_CONTROL_DATA =
new MediaRenderer.ControlData(new String[]
{
"showcontrols", "false"
},
true, // autosizes
0,
0);
// =-= bts what about close captioning?
// =-= bts Is unsupported mime types the right way to go, how about supported
// mimetypes instead?
//
// ControlSet shared by all primary content types on WMP 6.4
//
private static final MediaRenderer.ControlSet _WINDOWS_6_4_CONTROL_SET = new MediaRenderer.ControlSet(
new Object[]
{
CoreMedia.CONTROLS_NONE, _WMP_6_4_NONE_VISIBLE_CONTROL_DATA,
CoreMedia.CONTROLS_NONE_VISIBLE, _WMP_6_4_NONE_VISIBLE_CONTROL_DATA,
CoreMedia.CONTROLS_MINIMAL, new MediaRenderer.ControlData(new String[]
{
"showcontrols", "true",
"showaudiocontrols", "false",
"showpositioncontrols", "false",
"showtracker", "false",
},
false, // no autosize
_WMP_MINIMAL_CONTROLS_HEIGHT,
_WMP_MINIMAL_CONTROLS_WIDTH),
CoreMedia.CONTROLS_TYPICAL, new MediaRenderer.ControlData(null,// this is the default
true, // autosizes
_WMP_CONTROL_HEIGHT,
_WMP_ALL_CONTROLS_WIDTH),
CoreMedia.CONTROLS_ALL, new MediaRenderer.ControlData(new String[]
{
"showdisplay", "true",
"showgotobar", "true",
"showstatusbar", "true",
},
true, // autosizes
_WMP_ALL_CONTROLS_HEIGHT,
_WMP_ALL_CONTROLS_WIDTH),
});
private static final MediaRenderer.PlayerData _WINDOWS_6_4_PLAYER_DATA =
new MediaRenderer.PlayerData(
CoreMedia.PLAYER_WINDOWS, // player type
true, // autostart by default
"1", // autostartTrueValue
"0", // autostartFalseValue
false, // can't always autosize
null, // min player height
"autostart", // autostartParamName
"filename", // sourceParamName
"playcount", // infiniteLoopParamName,
0, // infiniteLoopParamValue
"playcount", // playCountParamName
"http://www.microsoft.com/Windows/MediaPlayer/", // pluginsPage
_WMP_CODE_BASE, // <Object> CodeBase
"application/x-mplayer2", // playerMimeType
_WMP_6_4_CLASS_ID, // <Object> ClassID
"application/x-oleobject", // overrideContentType
null, // wireImageToControlsParamName
null, // imageWindowControlData
new Object[]
{
"audio", _WINDOWS_6_4_CONTROL_SET,
"video", _WINDOWS_6_4_CONTROL_SET,
},
new String[] // mime-types not supported by Windows Media Player 6.4
{
_QUICKTIME_MIME_TYPE,
_REAL_AUDIO_MIME_TYPE,
_REAL_AUDIO_PN_MIME_TYPE,
_REAL_AUDIO_PLUGIN_MIME_TYPE,
_REAL_VIDEO_MIME_TYPE,
_REAL_VIDEO_PN_MIME_TYPE,
_REAL_VIDEO_PLUGIN_MIME_TYPE,
});
//
// Meta Data for the Real Player
//
private static final Number _REAL_MINIMAL_WIDTH = Integer.valueOf(44);
private static final int _REAL_MINIMAL_HEIGHT = 26;
private static final Number _REAL_TYPICAL_WIDTH = Integer.valueOf(220);
private static final int _REAL_TYPICAL_HEIGHT = 36;
private static final Number _REAL_ALL_WIDTH = Integer.valueOf(375);
private static final int _REAL_ALL_HEIGHT = 100;
// null control data
private static final MediaRenderer.ControlData _NULL_CONTROL_DATA =
new MediaRenderer.ControlData(null,
false, // no autosize
0,
0);
// control data for showing image window on Real Player
private static final MediaRenderer.ControlData _REAL_VIDEO_IMAGE_WINDOW_CONTROL_DATA =
new MediaRenderer.ControlData(new String[]
{
"controls", "ImageWindow",
"maintainAspect", "true"
},
false, // no autosize
0,
0);
private static final MediaRenderer.ControlData _REAL_MINIMAL_CONTROL_DATA =
new MediaRenderer.ControlData(new String[]
{
"controls", "PlayButton"
},
false, // no autosize
_REAL_MINIMAL_HEIGHT,
_REAL_MINIMAL_WIDTH);
// control data for showing typical controls on Real Player
private static final MediaRenderer.ControlData _REAL_TYPICAL_CONTROL_DATA =
new MediaRenderer.ControlData(new String[]{"controls", "ControlPanel"},
false, // no autosize
_REAL_TYPICAL_HEIGHT,
_REAL_TYPICAL_WIDTH);
// control data for showing all controls on Real Player
private static final MediaRenderer.ControlData _REAL_ALL_CONTROL_DATA =
new MediaRenderer.ControlData(new String[]{"controls", "All"},
false, // no autosize
_REAL_ALL_HEIGHT,
_REAL_ALL_WIDTH);
private static final MediaRenderer.ControlData _REAL_AUDIO_NONE_VISIBLE_CONTROL_DATA =
new MediaRenderer.ControlData(new String[]{"controls", ""},
false, // no autosize
0,
0);
private static final MediaRenderer.PlayerData _REAL_PLAYER_DATA =
new MediaRenderer.PlayerData(
CoreMedia.PLAYER_REAL, // player type
false, // no autostart by default
"true", // autostartTrueValue
"false", // autostartFalseValue
false, // can't always autosize
null, // min player height
"autostart", // autostartParamName
"src", // sourceParamName
"loop", // infiniteLoopParamName,
"true", // infiniteLoopParamValue
"numloop", // playCountParamName
"http://www.real.com/player/", // pluginsPage
"http://www.real.com/player/", // <Object> CodeBase
"audio/x-pn-realaudio-plugin", // playerMimeType
_RP_CLASS_ID, // <Object> ClassID
null, // overrideContentType
"console", // wireImageToControlsParamName
_REAL_VIDEO_IMAGE_WINDOW_CONTROL_DATA, // imageWindowControlData
new Object[]
{
"audio", new MediaRenderer.ControlSet(new Object[]
{
CoreMedia.CONTROLS_NONE, _REAL_AUDIO_NONE_VISIBLE_CONTROL_DATA,
CoreMedia.CONTROLS_NONE_VISIBLE, _REAL_AUDIO_NONE_VISIBLE_CONTROL_DATA,
CoreMedia.CONTROLS_MINIMAL, _REAL_MINIMAL_CONTROL_DATA,
CoreMedia.CONTROLS_TYPICAL, _REAL_TYPICAL_CONTROL_DATA,
CoreMedia.CONTROLS_ALL, _REAL_ALL_CONTROL_DATA,
}),
"video", new MediaRenderer.ControlSet(new Object[]
{
CoreMedia.CONTROLS_NONE, _NULL_CONTROL_DATA,
CoreMedia.CONTROLS_NONE_VISIBLE, _NULL_CONTROL_DATA,
CoreMedia.CONTROLS_MINIMAL, _REAL_MINIMAL_CONTROL_DATA,
CoreMedia.CONTROLS_TYPICAL, _REAL_TYPICAL_CONTROL_DATA,
CoreMedia.CONTROLS_ALL, _REAL_ALL_CONTROL_DATA,
}),
},
null); // mime types not supported by real
private static final Object[] _PLAYER_DATA = new Object[]
{
CoreMedia.PLAYER_LINK, _LINK_PLAYER_DATA,
CoreMedia.PLAYER_QUICKTIME, _QUICKTIME_PLAYER_DATA,
CoreMedia.PLAYER_WINDOWS, _WINDOWS_6_4_PLAYER_DATA,
CoreMedia.PLAYER_REAL, _REAL_PLAYER_DATA,
};
// maps extensions to MIME types
private static final String[] _EXTENSION_TO_MIME_TYPE = new String[]
{
"aif", _AIFF_MIME_TYPE,
"aifc", _AIFF_MIME_TYPE,
"aiff", _AIFF_MIME_TYPE,
"art", _ART_MIME_TYPE,
"asf", _ASF_MIME_TYPE,
"asx", _ASF_MIME_TYPE,
"au", _ULAW_MIME_TYPE,
"avi", _AVI_MIME_TYPE,
"bmp", _BMP_MIME_TYPE,
"gif", _GIF_MIME_TYPE,
"htm", _HTML_MIME_TYPE,
"html", _HTML_MIME_TYPE,
"ief", _IEF_IMAGE_MIME_TYPE,
"jfif", _JPEG_MIME_TYPE,
"jpe", _JPEG_MIME_TYPE,
"jpg", _JPEG_MIME_TYPE,
"jpeg", _JPEG_MIME_TYPE,
"kar", _MIDI_MIME_TYPE,
"m15", _MPEG_VIDEO_MIME_TYPE,
"m75", _MPEG_VIDEO_MIME_TYPE,
"m1a", _MPEG_VIDEO_MIME_TYPE,
"m1s", _MPEG_VIDEO_MIME_TYPE,
"m1v", _MPEG_VIDEO_MIME_TYPE,
"mid", _MIDI_MIME_TYPE,
"midi", _MIDI_MIME_TYPE,
"mov", _QUICKTIME_MIME_TYPE,
"movie",_SGI_MOVIE_MIME_TYPE,
"mpe", _MPEG_VIDEO_MIME_TYPE,
"mpg", _MPEG_VIDEO_MIME_TYPE,
"mpga", _MPEG_AUDIO_MIME_TYPE,
"mpeg", _MPEG_VIDEO_MIME_TYPE,
"mp2", _MPEG_AUDIO_MIME_TYPE,
"mp3", _MPEG_AUDIO_MIME_TYPE,
"mpa", _MPEG_AUDIO_MIME_TYPE,
"mpm", _MPEG_AUDIO_MIME_TYPE,
"mp2v", _MPEG2_VIDEO_MIME_TYPE,
"mpv2", _MPEG2_VIDEO_MIME_TYPE,
"pbm", _PORTABLE_BITMAP_MIME_TYPE,
"pgm", _PORTABLE_GRAYMAP_MIME_TYPE,
"pnm", _PORTABLE_ANYMAP_MIME_TYPE,
"pic", _PICT_MIME_TYPE,
"pict", _PICT_MIME_TYPE,
"png", _PNG_MIME_TYPE,
"qt", _QUICKTIME_MIME_TYPE,
"ra", _REAL_AUDIO_MIME_TYPE,
"ram", _REAL_AUDIO_PN_MIME_TYPE,
"ras", _CMU_RASTER_MIME_TYPE,
"rgb", _RGB_MIME_TYPE,
"rm", _REAL_AUDIO_PN_MIME_TYPE,
"rpg", _REAL_AUDIO_PLUGIN_MIME_TYPE,
"rpm", _REAL_AUDIO_PLUGIN_MIME_TYPE,
"rv", _REAL_VIDEO_MIME_TYPE,
"smf", _MIDI_MIME_TYPE,
"smi", _SMIL_MIME_TYPE,
"smil", _SMIL_MIME_TYPE,
"snd", _ULAW_MIME_TYPE,
"tif", _TIFF_MIME_TYPE,
"tiff", _TIFF_MIME_TYPE,
"txt", _PLAIN_TEXT_MIME_TYPE,
"ulw", _ULAW_MIME_TYPE,
"wav", _WAV_MIME_TYPE,
"wma", _WMA_MIME_TYPE,
"wmv", _WMV_MIME_TYPE,
"wvx", _WVX_MIME_TYPE,
"xbm", _X_BITMAP_MIME_TYPE,
"xpm", _X_PIXMAP_MIME_TYPE,
"xwd", _X_WINDOW_DUMP_MIME_TYPE,
};
// Preferred Players for MimeTypes
private static final Object[] _PREFERRED_MIME_PLAYERS = new Object[]
{
_AIFF_MIME_TYPE, CoreMedia.PLAYER_QUICKTIME,
_ASF_MIME_TYPE, CoreMedia.PLAYER_WINDOWS,
_AVI_MIME_TYPE, CoreMedia.PLAYER_WINDOWS,
_QUICKTIME_MIME_TYPE, CoreMedia.PLAYER_QUICKTIME,
_REAL_AUDIO_MIME_TYPE, CoreMedia.PLAYER_REAL,
_REAL_AUDIO_PN_MIME_TYPE, CoreMedia.PLAYER_REAL,
_REAL_AUDIO_PLUGIN_MIME_TYPE, CoreMedia.PLAYER_REAL,
_REAL_VIDEO_MIME_TYPE, CoreMedia.PLAYER_REAL,
_REAL_VIDEO_PN_MIME_TYPE, CoreMedia.PLAYER_REAL,
_REAL_VIDEO_PLUGIN_MIME_TYPE, CoreMedia.PLAYER_REAL,
_WMA_MIME_TYPE, CoreMedia.PLAYER_WINDOWS,
_WMV_MIME_TYPE, CoreMedia.PLAYER_WINDOWS,
_WVX_MIME_TYPE, CoreMedia.PLAYER_WINDOWS,
};
//
// Object constants for OS's
//
private static final Integer _WINDOWS_OS =
TrinidadAgent.OS_WINDOWS;
private static final Integer _MAC_OS =
TrinidadAgent.OS_MACOS;
private static final Integer _SOLARIS_OS =
TrinidadAgent.OS_SOLARIS;
// Preferred Players for Operating Systems
/* CURRENTLY UNUSED
private static final Object[] _PREFERRED_OS_PLAYERS = new Object[]
{
_WINDOWS_OS, PLAYER_WINDOWS,
_MAC_OS, PLAYER_QUICKTIME,
_SOLARIS_OS, PLAYER_WINDOWS,
};
*/
// Supported players on each OS, in prference order
private static final Object[] _SUPPORTED_OS_PLAYERS = new Object[]
{
_WINDOWS_OS, new Object[]{CoreMedia.PLAYER_WINDOWS,
CoreMedia.PLAYER_QUICKTIME,
CoreMedia.PLAYER_REAL},
_MAC_OS, new Object[]{CoreMedia.PLAYER_QUICKTIME,
CoreMedia.PLAYER_WINDOWS,
CoreMedia.PLAYER_REAL},
_SOLARIS_OS, new Object[]{CoreMedia.PLAYER_WINDOWS},
};
//
// default sizes for different primary mime types
//
private static Object[] _DEFAULT_INNER_SIZES = new Object[]
{
"audio", new Number[]{0,
0},
"video", new Number[]{200,
150},
};
private static final int _DEFAULT_INNER_WIDTH_INDEX = 0;
private static final int _DEFAULT_INNER_HEIGHT_INDEX = 1;
// map of mime types to preferred players
private static HashMap<Object, Object> _sPreferredMimePlayers;
// map of Operating Systems to preferred players
private static HashMap<Integer, String> _sPreferredOSPlayers;
// map of Operating Systems to HashSet of supported players
private static HashMap<Integer, HashSet<Object>> _sSupportedOSPlayers;
// map the in mime type to the cannonical mime type
private static HashMap<Object, Object> _sMimeTypeRemapper;
// maps the extension to the mime type
private static HashMap<Object, Object> _sExtensionMap;
// maps a player name to its player data
private static HashMap<Object, Object> _sPlayerData;
// maps a primary content type to a default inner size
private static HashMap<Object, Object> _sDefaultInnerSizes;
static
{
// initialize data for supported players
_sPlayerData = _createHashMap(_PLAYER_DATA);
// initialize the mapping of mime types to preferred players
_sPreferredMimePlayers = _createHashMap(_PREFERRED_MIME_PLAYERS);
//
// create the set of all OS's that have players. The first player
// listed is the preferred player for that OS.
//
int supportedOSPlayersLength = _SUPPORTED_OS_PLAYERS.length;
int hashSize = (int)(supportedOSPlayersLength * 0.75);
_sSupportedOSPlayers = new HashMap<Integer, HashSet<Object>>(hashSize);
_sPreferredOSPlayers = new HashMap<Integer, String>(hashSize);
for (int i = 0; i < supportedOSPlayersLength; i += 2)
{
Integer os = (Integer)_SUPPORTED_OS_PLAYERS[i];
Object[] players = (Object[])_SUPPORTED_OS_PLAYERS[i + 1];
if ((players != null) && (players.length > 0))
{
// add the players for this OS to the mapping of OSs to
// player sets
_sSupportedOSPlayers.put(os, _createHashSet(players));
// record the preferred player for this OS
_sPreferredOSPlayers.put(os, (String)players[0]);
}
}
// initialize the mime type remapper
_sMimeTypeRemapper = _createHashMap(_MIME_TYPE_REMAPPER);
// initialize the extension map
_sExtensionMap = _createHashMap(_EXTENSION_TO_MIME_TYPE);
// initialize the map of default inner sizes
_sDefaultInnerSizes = _createHashMap(_DEFAULT_INNER_SIZES);
}
private PropertyKey _sourceKey;
private PropertyKey _playerKey;
private PropertyKey _contentTypeKey;
private PropertyKey _autostartKey;
private PropertyKey _playCountKey;
private PropertyKey _controlsKey;
private PropertyKey _standbyTextKey;
private PropertyKey _widthKey;
private PropertyKey _heightKey;
private PropertyKey _innerWidthKey;
private PropertyKey _innerHeightKey;
}