?? .#mediarenderer.java.1.4
字號(hào):
package no.auc.one.portableplayer.communication.mediarenderer;
import java.io.*;
import java.util.*;
import javax.microedition.io.*;
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import org.apache.log4j.*;
import no.auc.one.portableplayer.communication.*;
import no.auc.one.portableplayer.utils.*;
// XXX A lot of the functionality of this class is common with MediaServer. Should be
// possible to refactor these, and move some of the functionality up to the
// super class (UPnPDevice)
/**
* Functionality for interacting with a UPnP Media Renderer. Currently it
* only supports the AV Transport service.
*
* Usage example:
* MediaRenderer mr = new MediaRenderer();
* for(Enumerable e = mr.getMediaServers(); e.hasMoreElements(); ) {
* // Here you can interact with the specific media renderers discovered.
* }
*/
public class MediaRenderer extends UPnPDevice implements Cloneable, CancelAction {
private static Logger LOG = Logger.getLogger("MR");
private static MediaRenderer[] mediaRenderers = null;
private AVTransportService avTransport = null;
private RenderingControlService rcontrol = null;
private UPnPDiscovery discoRenderers = null;
private boolean isUpdatingList = false;
/**
* Default constructor.
*/
public MediaRenderer() {
super();
}
/**
* Creates a new MediaRenderer based on the parameters.
*
* @param dev UPnPDevice to use as the base for this class. Will be
* copied, and no reference stored.
*
* @param avt Reference to a AVTransportService instance to be associated
* with this class.
* @param rcs Reference to a RenderingControlService instance to be associated
* with this class.
*/
public MediaRenderer(UPnPDevice dev, AVTransportService avt, RenderingControlService rcs) {
super(dev.getFriendlyName(), dev.getURLBase());
this.avTransport = avt;
this.rcontrol = rcs;
}
/**
* Clone this class instance
*
* @return Copy of this device.
*/
public Object clone() {
MediaRenderer mr = new MediaRenderer(
(UPnPDevice)this,
(AVTransportService)avTransport.clone(),
(RenderingControlService)rcontrol.clone());
return mr;
}
public void cancel() throws IOException {
discoRenderers.cancel();
}
/**
* Return the available media renderers found on the local network. Will
* update the list of available media renderers if it does not currently
* exist.
*
* @return Let you enumerate the discovered renderers.
*/
// TODO Add auto-update for discovery (each hour or similar) see
// MediaServer::getMediaServers for more info
public Enumeration getMediaRenderers() throws NoSuchElementException,
IOException
{
if (mediaRenderers == null) {
throw new IllegalStateException(
"Media Renderers have not been discovered yet. Do updateMediaRendererList first.");
}
MediaRenderer[] rendererListClone = null;
if (mediaRenderers != null) {
rendererListClone = new MediaRenderer[mediaRenderers.length];
for(int i = 0; i < mediaRenderers.length; i++) {
rendererListClone[i] = (MediaRenderer)mediaRenderers[i].clone();
}
}
return new MediaRendererEnumeration(rendererListClone);
}
public MediaRenderer getMediaRenderer(int index) throws NoSuchElementException, IOException {
MediaRenderer mr = null;
if (mediaRenderers == null) {
throw new IllegalStateException(
"Media Renderers have not been discovered yet. Do updateMediaRendererList first.");
}
if (mediaRenderers != null) {
mr = (MediaRenderer)mediaRenderers[index].clone();
}
return mr;
}
public void updateMediaRendererList() throws IOException
{
if (isUpdatingList) {
return;
} else {
isUpdatingList = true;
}
try {
discoRenderers = new UPnPDiscovery();
String[] rendererLocationUrls = discoRenderers.start(
"urn:schemas-upnp-org:device:MediaRenderer:1",
5); // max duration set to 5 seconds
if (rendererLocationUrls == null || rendererLocationUrls.length <= 0) {
LOG.debug("No media renderers discovered.");
mediaRenderers = null;
return;
} else {
LOG.debug(
"Media Renderers discovered: " + rendererLocationUrls.length);
}
// Need to make the following more robust.
// First add all available renderers to a vector. Then add all these devices
// to the mediaRenderers list
Vector availableRenderers = new Vector();
SAXParser parser = null;
try {
SAXParserFactory pfactory = SAXParserFactory.newInstance();
parser = pfactory.newSAXParser();
} catch (ParserConfigurationException pce) {
LOG.fatal("PCE exception in updateMediaRendererList");
LOG.fatal(pce);
} catch (SAXException se) {
LOG.fatal("SAXException in updateMediaRendererList");
LOG.fatal(se);
}
if (parser == null) {
mediaRenderers = null;
return;
}
for(int index = 0; index < rendererLocationUrls.length; index++)
{
HttpConnection conn = null;
try{
LOG.debug(
"MR" + index + ": " + rendererLocationUrls[index]);
conn = (HttpConnection)Connector.open(
rendererLocationUrls[index]);
conn.setRequestMethod(HttpConnection.GET);
conn.setRequestProperty("Content-Length","0");
MediaRenderer mr = new MediaRenderer();
MediaRendererDeviceDescriptionHandler mrddHandler = new
MediaRendererDeviceDescriptionHandler(
mr,
rendererLocationUrls[index]);
parser.parse(conn.openInputStream(), mrddHandler);
conn.close();
LOG.debug(
"MediaRenderer found (" + index + ")" +
" Name: " + mr.friendlyName +
" URLBase: " + mr.urlBase +
" AVT: " + mr.avTransport.toString() +
" RCS: " + mr.rcontrol.toString());
availableRenderers.addElement(mr);
} catch (SAXException se) {
LOG.fatal("SAXExceptio in updateMediaRendererList");
LOG.fatal(se);
} catch (ConnectionNotFoundException cnfe) {
LOG.fatal("Connection not found.");
LOG.fatal(cnfe);
} catch (IOException ioe) {
LOG.fatal(
"Error while getting device description for MR" + index);
LOG.fatal(ioe);
}
}
if (availableRenderers == null || availableRenderers.size() <= 0) {
mediaRenderers = null;
return;
}
mediaRenderers = new MediaRenderer[availableRenderers.size()];
for(int i = 0; i < availableRenderers.size(); i++) {
mediaRenderers[i] = (MediaRenderer)availableRenderers.elementAt(i);
}
} finally {
discoRenderers = null;
isUpdatingList = false;
}
}
/**
* Get this device's associated AV Transport Service instance.
*
* @return AV Transport Service instance.
*/
public AVTransportService getAVTransportService() {
return avTransport;
}
/**
* Get this device's associated Rendering Control Service instance.
*
* @return Rendering Control instance.
*/
public RenderingControlService getRenderingControlService() {
return rcontrol;
}
/**
* Used to parse the device description of Media Renderers.
*/
private class MediaRendererDeviceDescriptionHandler extends DefaultHandler{
private MediaRenderer mr;
private Vector services = new Vector();
private Stack tagStack = new Stack();
private String locationURL;
public MediaRendererDeviceDescriptionHandler(MediaRenderer mr, String url) {
this.mr = mr;
locationURL = url;
}
public void startElement(
String uri,
String localName,
String qName,
Attributes attributes) throws SAXException
{
if(qName.equals("service")) {
// Should know if the device description contains an URLBase
// element or not at this point
if(mr.urlBase == null || mr.urlBase == "") {
// Use locationURL as URLBase
mr.urlBase = getHostAndPort(locationURL);
}
services.addElement(new UPnPService());
}
tagStack.push(qName);
}
public void characters(char[] ch, int start, int length) throws SAXException {
String chars = new String(ch, start, length).trim();
if(chars.length() > 0) {
String qName = (String)tagStack.peek();
if (qName.equals("friendlyName")) {
mr.friendlyName = chars;
} else if (qName.equals("URLBase")) {
mr.urlBase = chars;
} else if (qName.equals("serviceType")) {
UPnPService currentService = (UPnPService)services.lastElement();
currentService.setServiceType(chars);
} else if (qName.equals("serviceId")) {
UPnPService currentService = (UPnPService)services.lastElement();
currentService.setServiceId(chars);
} else if (qName.equals("controlURL")) {
UPnPService currentService = (UPnPService)services.lastElement();
currentService.setControlURL(mr.urlBase + chars);
} else if (qName.equals("SCPDURL")) {
UPnPService currentService = (UPnPService)services.lastElement();
currentService.setSCPDURL(mr.urlBase + chars);
} else if (qName.equals("eventSubURL")) {
UPnPService currentService = (UPnPService)services.lastElement();
currentService.setEventSubURL(mr.urlBase + chars);
}
}
}
public void endElement(String uri, String localName, String qName) throws SAXException {
tagStack.pop();
}
public void endDocument() throws SAXException {
if (services == null) {
return;
}
for (int i=0; i < services.size(); i++){
UPnPService currentService = (UPnPService)services.elementAt(i);
if (currentService == null) {
LOG.debug("Null service detected. Possibly a bug somewhere?");
continue;
}
if (currentService.getServiceType().equals(
"urn:schemas-upnp-org:service:AVTransport:1")){
mr.avTransport = new AVTransportService(currentService);
} else if (currentService.getServiceType().equals(
"urn:schemas-upnp-org:service:RenderingControl:1")){
mr.rcontrol = new RenderingControlService(currentService);
} else {
LOG.debug("Unknown service found: " + currentService.getServiceType());
}
}
}
/**
* Analyze the rendererLocationUrls to get only the address and port
* @param url URL to find host and port of.
* @return Returns host and port of an URL
*/
private String getHostAndPort(String url) {
int ss = 0;
for (int i = 8; i < url.length(); i++) {
ss=url.substring(8).indexOf('/');
}
return url.substring(0, ss + 9);
}
}
/**
* Used for enumerating available Media Renderers.
*/
private class MediaRendererEnumeration implements Enumeration {
private MediaRenderer[] rendererList;
private int currentIndex;
public MediaRendererEnumeration (
MediaRenderer[] renderers)
{
rendererList = renderers;
currentIndex = 0;
}
public boolean hasMoreElements() {
if (rendererList == null || currentIndex > (rendererList.length - 1)) {
return false;
} else {
return true;
}
}
public Object nextElement() {
if (hasMoreElements()) {
return rendererList[currentIndex++];
} else {
throw new NoSuchElementException("No more Media Renderers available");
}
}
}
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -