blob: 7555f538adff00e3a0b497b3741469b5d843bc49 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2011 Ministry of Internal Affairs and Communications (MIC).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Yasuharu GOTOU (MIC) - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.examples.michecker.smil;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Vector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.actf.examples.michecker.caption.CaptionData;
import org.eclipse.actf.examples.michecker.caption.CaptionDataFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* SMIL viewer front end. See main() for usage.
*
*/
public class SMILReader {
private final boolean DEBUG = false;
private URL fileUrl;
private Vector<CaptionData> captions;
/**
* reads and parses a file with given <code>filePath</code>.
*
* @param filePath
* {@link URL} and local file path are allowed
* @return true if it successes reading given file.
*/
public boolean read(String filePath) {
try {
fileUrl = new URL(filePath);
} catch (MalformedURLException e1) {
if (DEBUG)
System.err
.println("- failed to treat given path as URL. try to interpret as local file path...");
URI uri = (new File(filePath)).toURI();
try {
fileUrl = uri.toURL();
} catch (MalformedURLException e) {
if (DEBUG)
System.err
.println("- failed to treat as local file. I give it up. abort.");
return false;
}
}
assert fileUrl != null;
if (DEBUG)
System.out.println("-- reading " + filePath + "...");
captions = new Vector<CaptionData>();
try {
DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
df.setExpandEntityReferences(false);
df.setFeature(
"http://apache.org/xml/features/nonvalidating/load-external-dtd",
false);
DocumentBuilder db = df.newDocumentBuilder();
if (DEBUG) {
System.out.println(new SimpleDateFormat("HH:mm:ss.SSS")
.format(new Date()) + " parsing start");
}
Document doc = db.parse(filePath);
if (DEBUG) {
System.out.println(new SimpleDateFormat("HH:mm:ss.SSS")
.format(new Date()) + " parsing end");
System.out.println("--- checking file format...");
}
Element root = doc.getDocumentElement();
if (DEBUG) {
System.out.println(root.getLocalName());
System.out.println(root.getTagName());
System.out.println(root.getNamespaceURI());
System.out.println(root.getNodeName());
}
NodeList headNl = root.getElementsByTagName("head");
NodeList bodyNl = root.getElementsByTagName("body");
if (headNl.getLength() == 1 && bodyNl.getLength() == 1) {
if (DEBUG)
System.out.println(" OK");
} else {
if (DEBUG)
System.out.println(" NG");
return false;
}
if (DEBUG)
System.out.println("--- reading metadata...");
NodeList metaNl = ((Element) headNl.item(0))
.getElementsByTagName("meta");
for (int i = 0; i < metaNl.getLength(); i++) {
Element meta = (Element) (metaNl.item(i));
if (DEBUG)
System.out.println(" " + meta.getAttribute("name") + ": "
+ meta.getAttribute("content"));
}
if (DEBUG)
System.out.println("--- reading structure...");
Element body = (Element) bodyNl.item(0);
parseElement(0.0, 1, body);
if (DEBUG)
System.out.println("-- reading completed.");
return true;
} catch (Exception e) {
return false;
}
}
/**
* Parses a par, seq, or excl container and returns a relative end time.
*
* @param time
* The global time when this media starts.
* @param container
* @returns The global when this media ends.
*/
private double parseElement(double time, int indent, Element e) {
String name = e.getTagName().toLowerCase();
double dur = Double.NaN;
// indentation
for (int j = 0; j < indent; j++) {
// System.out.print(" ");
}
// System.out.print(time + ": " + name);
// if not supported, warn and return
if (!isSupported(name)) {
// System.err.println("- unsupported element: " + name);
// System.out.println("");
return time;
}
if (hasSynchAttributes(name)) {
String durStr = e.getAttribute("dur");
// System.out.print(" [" + e.getAttribute("begin") + "]");
// System.out.print(" [" + durStr + "]");
if (durStr.length() > 0)
dur = ClockValueParser.parseDuration(e.getAttribute("dur"));
}
// System.out.println("");
// create a CaptionData instance
if (name.matches("text(stream)?")) {
try {
Vector<CaptionData> v = CaptionDataFactory.createCaptionData(
time, new URL(fileUrl, e.getAttribute("src")));
if (v != null) {
captions.addAll(v);
}
} catch (MalformedURLException e1) {
// System.err.println("- invalid path for text file. skipped.");
}
}
// show children
NodeList nl = e.getChildNodes();
double childBegin = time;
double childEnd = time;
for (int i = 0; i < nl.getLength(); i++) {
if (nl.item(i).getNodeType() == Node.ELEMENT_NODE) {
double endTime = parseElement(childBegin, indent + 1,
(Element) nl.item(i));
if (name.matches("body|par|switch")) {
childEnd = Math.max(childEnd, endTime);
} else if (name.equals("seq")) {
childBegin = childEnd = endTime;
} else { // media element
; // do nothing
}
}
}
if (Double.isNaN(dur))
return childEnd;
else
return time + dur;
}
@SuppressWarnings("unused")
private boolean isTimeContainer(String tagName) {
return tagName.matches("body|par|seq");
}
private boolean isSupported(String tagName) {
return tagName
.matches("body|seq|par|img|audio|text|param|video|switch|textstream");
}
private boolean hasSynchAttributes(String tagName) {
return tagName.matches("body|seq|par|img|audio|text|video|textstream"); // param
// is
// excluded
}
public Vector<CaptionData> getCaptions() {
return captions;
}
public static void main(String[] args) {
SMILReader viewer = new SMILReader();
boolean b = viewer.read(args[0]);
System.out.println(b);
if (b) {
System.out.println("\n-- showing captions...");
Vector<CaptionData> cp = viewer.getCaptions();
for (CaptionData captionData : cp) {
System.out.println(captionData.getTime() + ": "
+ captionData.getCaptionText());
}
}
System.out.println("-- done.");
}
}