2002-10-25 20:19:56 +00:00
|
|
|
/*
|
|
|
|
The contents of this file are subject to the THDL Open Community License
|
|
|
|
Version 1.0 (the "License"); you may not use this file except in compliance
|
2002-11-14 21:13:08 +00:00
|
|
|
with the License. You may obtain a copy of the License on the THDL web site
|
2002-10-25 20:19:56 +00:00
|
|
|
(http://www.thdl.org/).
|
|
|
|
|
2002-11-14 21:13:08 +00:00
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
|
|
|
License for the specific terms governing rights and limitations under the
|
|
|
|
License.
|
2002-10-25 20:19:56 +00:00
|
|
|
|
|
|
|
The Initial Developer of this software is the Tibetan and Himalayan Digital
|
|
|
|
Library (THDL). Portions created by the THDL are Copyright 2001 THDL.
|
2002-11-14 21:13:08 +00:00
|
|
|
All Rights Reserved.
|
2002-10-25 20:19:56 +00:00
|
|
|
|
|
|
|
Contributor(s): ______________________________________.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package org.thdl.media;
|
|
|
|
|
|
|
|
import java.awt.*;
|
|
|
|
import java.net.*;
|
2002-11-02 20:20:30 +00:00
|
|
|
import java.util.*;
|
|
|
|
import javax.swing.event.EventListenerList;
|
|
|
|
|
|
|
|
import org.thdl.savant.AnnotationPlayer; //should move AP to org.thdl.annotation
|
|
|
|
|
2002-10-25 20:19:56 +00:00
|
|
|
|
|
|
|
public abstract class SmartMoviePanel extends Panel
|
|
|
|
{
|
2002-11-02 20:20:30 +00:00
|
|
|
//fields
|
|
|
|
private EventListenerList listenerList = new EventListenerList();
|
|
|
|
|
|
|
|
private Vector orderStartID = null, orderEndID = null;
|
|
|
|
private Stack pileStart = null, pileEnd = null;
|
|
|
|
private Hashtable hashStart = null, hashEnd = null;
|
|
|
|
|
|
|
|
private Timer annTimer = null;
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
public void addAnnotationPlayer(AnnotationPlayer ap)
|
|
|
|
{
|
|
|
|
listenerList.add(AnnotationPlayer.class, ap);
|
|
|
|
}
|
|
|
|
public void removeAnnotationPlayer(AnnotationPlayer ap)
|
|
|
|
{
|
|
|
|
listenerList.remove(AnnotationPlayer.class, ap);
|
|
|
|
}
|
|
|
|
public void removeAllAnnotationPlayers() {
|
|
|
|
listenerList = new EventListenerList();
|
|
|
|
}
|
|
|
|
private void fireStartAnnotation(String id)
|
|
|
|
{
|
|
|
|
//see javadocs on EventListenerList for how following array is structured
|
|
|
|
Object[] listeners = listenerList.getListenerList();
|
|
|
|
|
|
|
|
for (int i = listeners.length-2; i>=0; i-=2)
|
|
|
|
{
|
|
|
|
if (listeners[i]==AnnotationPlayer.class)
|
|
|
|
((AnnotationPlayer)listeners[i+1]).startAnnotation(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void fireStopAnnotation(String id)
|
|
|
|
{
|
|
|
|
//see javadocs on EventListenerList for how following array is structured
|
|
|
|
Object[] listeners = listenerList.getListenerList();
|
|
|
|
|
|
|
|
for (int i = listeners.length-2; i>=0; i-=2)
|
|
|
|
{
|
|
|
|
if (listeners[i]==AnnotationPlayer.class)
|
|
|
|
((AnnotationPlayer)listeners[i+1]).stopAnnotation(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
public void initForSavant(String starts, String ends, String ids) {
|
|
|
|
String TAB_STARTS = starts;
|
|
|
|
String TAB_ENDS = ends;
|
|
|
|
String TAB_IDS = ids;
|
|
|
|
|
|
|
|
hashStart = new Hashtable();
|
|
|
|
hashEnd = new Hashtable();
|
|
|
|
pileStart = new Stack();
|
|
|
|
pileEnd = new Stack();
|
|
|
|
|
|
|
|
StringTokenizer stIDS = new StringTokenizer(TAB_IDS, ",");
|
|
|
|
StringTokenizer stSTARTS = new StringTokenizer(TAB_STARTS, ",");
|
|
|
|
StringTokenizer stENDS = new StringTokenizer(TAB_ENDS, ",");
|
|
|
|
while ((stIDS.hasMoreTokens()) && (stSTARTS.hasMoreTokens()) && (stENDS.hasMoreTokens())) {
|
|
|
|
String sID = stIDS.nextToken();
|
|
|
|
String sStart = stSTARTS.nextToken();
|
|
|
|
String sEnd = stENDS.nextToken();
|
|
|
|
try {
|
|
|
|
Integer start = new Integer(sStart);
|
|
|
|
hashStart.put(sID, start);
|
|
|
|
} catch (NumberFormatException err) {
|
|
|
|
hashStart.put(sID, new Integer(0));
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
Integer end = new Integer(sEnd);
|
|
|
|
hashEnd.put(sID, end);
|
|
|
|
} catch (NumberFormatException err) {
|
|
|
|
hashEnd.put(sID, new Integer(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector saveOrder = new Vector();
|
|
|
|
for (Enumeration e = hashStart.keys() ; e.hasMoreElements() ;) {
|
|
|
|
Object o = e.nextElement();
|
|
|
|
saveOrder.addElement(o);
|
|
|
|
}
|
|
|
|
orderStartID = new Vector();
|
|
|
|
while (saveOrder.size() > 0) {
|
|
|
|
int num = getMinusStart(saveOrder);
|
|
|
|
orderStartID.addElement(saveOrder.elementAt(num));
|
|
|
|
saveOrder.removeElementAt(num);
|
|
|
|
}
|
|
|
|
saveOrder = new Vector();
|
|
|
|
for (Enumeration e = hashEnd.keys() ; e.hasMoreElements() ;) {
|
|
|
|
Object o = e.nextElement();
|
|
|
|
saveOrder.addElement(o);
|
|
|
|
}
|
|
|
|
orderEndID = new Vector();
|
|
|
|
while (saveOrder.size() > 0) {
|
|
|
|
int num = getMinusEnd(saveOrder);
|
|
|
|
orderEndID.addElement(saveOrder.elementAt(num));
|
|
|
|
saveOrder.removeElementAt(num);
|
|
|
|
}
|
2002-11-14 21:13:08 +00:00
|
|
|
}
|
|
|
|
public String cmd_firstS() {
|
|
|
|
return (String)orderStartID.elementAt(0);
|
|
|
|
}
|
2002-11-02 20:20:30 +00:00
|
|
|
private int getMinusStart(Vector v) {
|
|
|
|
int index = 0;
|
|
|
|
String first = (String)v.elementAt(index);
|
|
|
|
Integer minus = (Integer)hashStart.get(first);
|
|
|
|
for (int i=0;i<v.size();i++) {
|
|
|
|
String s = (String)v.elementAt(i);
|
|
|
|
Integer f = (Integer)hashStart.get(s);
|
|
|
|
if (minus.intValue() > f.intValue()) {
|
|
|
|
minus = f;
|
|
|
|
index = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
private int getMinusEnd(Vector v) {
|
|
|
|
int index = 0;
|
|
|
|
String first = (String)v.elementAt(index);
|
|
|
|
Integer minus = (Integer)hashEnd.get(first);
|
|
|
|
for (int i=0;i<v.size();i++) {
|
|
|
|
String s = (String)v.elementAt(i);
|
|
|
|
Integer f = (Integer)hashEnd.get(s);
|
|
|
|
if (minus.intValue() > f.intValue()) {
|
|
|
|
minus = f;
|
|
|
|
index = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
public boolean cmd_isID(String theID) {
|
|
|
|
System.out.println(hashStart.containsKey(theID));
|
|
|
|
return hashStart.containsKey(theID);
|
|
|
|
}
|
2002-11-14 21:13:08 +00:00
|
|
|
public boolean cmd_playFrom(String fromID) {
|
2002-11-02 20:20:30 +00:00
|
|
|
Integer from = (Integer)hashStart.get(fromID);
|
|
|
|
try {
|
|
|
|
cmd_playSegment(from, null);
|
2002-11-14 21:13:08 +00:00
|
|
|
return true;
|
2002-11-02 20:20:30 +00:00
|
|
|
} catch (SmartMoviePanelException smpe) {
|
|
|
|
smpe.printStackTrace();
|
2002-11-14 21:13:08 +00:00
|
|
|
return false;
|
2002-11-02 20:20:30 +00:00
|
|
|
}
|
|
|
|
}
|
2002-11-14 21:13:08 +00:00
|
|
|
public boolean cmd_playS(String fromID) {
|
2002-11-02 20:20:30 +00:00
|
|
|
Integer from = (Integer)hashStart.get(fromID);
|
|
|
|
Integer to = (Integer)hashEnd.get(fromID);
|
|
|
|
try {
|
|
|
|
cmd_playSegment(from, to);
|
2002-11-14 21:13:08 +00:00
|
|
|
return true;
|
2002-11-02 20:20:30 +00:00
|
|
|
} catch (SmartMoviePanelException smpe) {
|
|
|
|
smpe.printStackTrace();
|
2002-11-14 21:13:08 +00:00
|
|
|
return false;
|
2002-11-02 20:20:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
public void launchAnnotationTimer() { //FIXME: should have upper limit - stop time else end time
|
|
|
|
if (listenerList.getListenerCount() == 0) //no annotation listeners
|
|
|
|
return;
|
|
|
|
|
|
|
|
int i = getCurrentTime();
|
|
|
|
Integer from = new Integer(i);
|
|
|
|
remplisPileStart(from, new Integer(getEndTime()));
|
|
|
|
if (annTimer != null) {
|
|
|
|
annTimer.cancel();
|
|
|
|
annTimer = null;
|
|
|
|
}
|
|
|
|
annTimer = new java.util.Timer(true);
|
|
|
|
annTimer.schedule(new TimerTask() {
|
|
|
|
public void run() {
|
|
|
|
cmd_nextEvent();
|
|
|
|
}}, 0, 15);
|
|
|
|
}
|
|
|
|
public void cancelAnnotationTimer() {
|
|
|
|
if (listenerList.getListenerCount() == 0) //no annotation listeners
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (annTimer != null) {
|
|
|
|
annTimer.cancel();
|
|
|
|
annTimer = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void cmd_nextEvent() {
|
|
|
|
Integer when = new Integer(getCurrentTime());
|
|
|
|
if (!pileStart.empty()) {
|
|
|
|
String id = (String)pileStart.peek();
|
|
|
|
Integer f = (Integer)hashStart.get(id);
|
|
|
|
if (when.intValue() >= f.intValue()) {
|
|
|
|
id = (String)pileStart.pop();
|
|
|
|
fireStartAnnotation(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!pileEnd.empty()) {
|
|
|
|
String id = (String)pileEnd.peek();
|
|
|
|
Integer f = (Integer)hashEnd.get(id);
|
|
|
|
if (when.intValue() >= f.intValue()) {
|
|
|
|
id = (String)pileEnd.pop();
|
|
|
|
fireStopAnnotation(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private void vide_Pile() {
|
|
|
|
while (!pileEnd.empty()) { //vider la pile des items qui ne sont pas
|
|
|
|
String id = (String)pileEnd.pop(); //encore fini
|
|
|
|
if (pileStart.search(id) == -1) {
|
|
|
|
fireStopAnnotation(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* empties the pile, and then reconstructs it to consist of all ids
|
|
|
|
whose start time or end time is included between start and end. */
|
|
|
|
|
|
|
|
private void remplisPileStart(Integer start, Integer end) {
|
|
|
|
vide_Pile();
|
|
|
|
pileStart.removeAllElements();
|
|
|
|
pileEnd.removeAllElements();
|
|
|
|
for (int i=orderEndID.size()-1; i!=-1; i--) {
|
|
|
|
String id = (String)orderEndID.elementAt(i);
|
|
|
|
Integer f = (Integer)hashEnd.get(id);
|
|
|
|
if ((f.intValue() > start.intValue()) && (f.intValue() <= end.intValue())) {
|
|
|
|
pileEnd.push(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* note: we are also interested in ids that begin before start,
|
|
|
|
provided they overlap with the interval start-end. */
|
|
|
|
|
|
|
|
for (int i=orderStartID.size()-1; i!=-1; i--) {
|
|
|
|
String id = (String)orderStartID.elementAt(i);
|
|
|
|
Integer f = (Integer)hashStart.get(id);
|
|
|
|
Integer f2 = (Integer)hashEnd.get(id);
|
|
|
|
if ( (f.intValue() >= start.intValue() && f.intValue() < end.intValue()) ||
|
|
|
|
(f.intValue() < start.intValue() && f2.intValue() > start.intValue())) {
|
|
|
|
pileStart.push(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
|
|
//constructor
|
|
|
|
public SmartMoviePanel(GridLayout layout)
|
|
|
|
{
|
|
|
|
super(layout);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
//abstract methods
|
|
|
|
|
|
|
|
|
|
|
|
public abstract String getIdentifyingName();
|
|
|
|
public abstract URL getMediaURL();
|
2002-10-25 20:19:56 +00:00
|
|
|
public abstract void setParentContainer(Container c);
|
|
|
|
|
|
|
|
//helper methods - initialize
|
|
|
|
public abstract void displayBorders(boolean borders) throws SmartMoviePanelException;
|
|
|
|
public abstract void displayController(boolean controller) throws SmartMoviePanelException;
|
|
|
|
public abstract void loadMovie(URL mediaUrl) throws SmartMoviePanelException;
|
2002-11-14 21:13:08 +00:00
|
|
|
|
2002-10-25 20:19:56 +00:00
|
|
|
//helper methods - control media
|
|
|
|
public abstract void cmd_playOn() throws SmartMoviePanelException;
|
|
|
|
public abstract void cmd_playSegment(Integer startTime, Integer stopTime) throws SmartMoviePanelException;
|
|
|
|
public abstract void cmd_stop() throws SmartMoviePanelException;
|
2002-11-14 21:13:08 +00:00
|
|
|
|
2002-10-25 20:19:56 +00:00
|
|
|
//helper methods - media status
|
|
|
|
public abstract boolean isInitialized();
|
|
|
|
public abstract boolean isPlaying();
|
|
|
|
public abstract int getCurrentTime();
|
|
|
|
public abstract int getEndTime();
|
|
|
|
|
|
|
|
//helper methods - cleanup
|
|
|
|
public abstract void destroy() throws SmartMoviePanelException;
|
|
|
|
}
|