Changed the build so that Savant and QuillDriver's builds include

Smart*Player.java, which are accessed via reflection.  Cleaned up the
code a bit so that it would compile in so doing.

Changed the 'options.txt' preferences file to reflect the new method
of selecting media players.
This commit is contained in:
dchandler 2002-10-27 19:12:13 +00:00
parent e4aa52a6eb
commit f26dd53da3
14 changed files with 108 additions and 951 deletions

View file

@ -204,6 +204,10 @@
value="org/thdl/savant/SavantShell.java"/> value="org/thdl/savant/SavantShell.java"/>
</antcall> </antcall>
<antcall target="compile-classes-accessed-by-reflection">
<param name="mybin" value="${savantbin}"/>
</antcall>
<!-- Copy the .rtf files; they're needed resources: --> <!-- Copy the .rtf files; they're needed resources: -->
<copy todir="${savantbin}/org/thdl/savant"> <copy todir="${savantbin}/org/thdl/savant">
<fileset dir="${source}"> <fileset dir="${source}">
@ -333,6 +337,10 @@
value="org/thdl/tib/text/TibetanHTML.java"/> value="org/thdl/tib/text/TibetanHTML.java"/>
</antcall> </antcall>
<antcall target="compile-classes-accessed-by-reflection">
<param name="mybin" value="${qdbin}"/>
</antcall>
<!-- Copy over QuillDriver-specific resources: --> <!-- Copy over QuillDriver-specific resources: -->
<copy todir="${qdbin}"> <copy todir="${qdbin}">
<fileset dir="${source}"> <fileset dir="${source}">
@ -1030,6 +1038,20 @@
</target> </target>
<target name="compile-classes-accessed-by-reflection"
description="Compiles classes that we access these via reflection (thus, compiling SavantShell and QDShell will not include them)">
<antcall target="our-internal-javac-task">
<param name="mybin" value="${qdbin}"/>
<param name="my.included.source.file"
value="org/thdl/media/SmartJMFPlayer.java"/>
</antcall>
<antcall target="our-internal-javac-task">
<param name="mybin" value="${qdbin}"/>
<param name="my.included.source.file"
value="org/thdl/media/SmartQT4JPlayer.java"/>
</antcall>
</target>
</project> </project>

5
dist/.cvsignore vendored Normal file
View file

@ -0,0 +1,5 @@
docs
java-web-start
lib
releases
source

View file

@ -19,9 +19,11 @@
######################### User Preferences ########################### ######################### User Preferences ###########################
############################################################################ ############################################################################
# Set this to qt4j if you wish to use QuickTime for Java, or to jmf if you # Set this to your preference of one of the following values:
# with to use Sun's Java Media Framework. #
thdl.media.player = qt4j # Framework: QuickTime for Java Value: org.thdl.media.SmartQT4JPlayer
# Framework: Java Media Framework Value: org.thdl.media.SmartJMFPlayer
thdl.media.player = org.thdl.media.SmartJMFPlayer
# Sets the Tibetan keyboard that Jskad uses on startup. # Sets the Tibetan keyboard that Jskad uses on startup.
# Here are the acceptable values: # Here are the acceptable values:

View file

@ -54,7 +54,7 @@ public class SmartJMFPlayer extends SmartMoviePanel implements ControllerListene
private Float to = null; private Float to = null;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
public static String getName() { public String getName() {
return "Java Media Framework"; return "Java Media Framework";
} }
public SmartJMFPlayer() { public SmartJMFPlayer() {

View file

@ -23,7 +23,7 @@ import java.net.*;
public abstract class SmartMoviePanel extends Panel public abstract class SmartMoviePanel extends Panel
{ {
public abstract static String getName(); public abstract String getName();
public abstract void setParentContainer(Container c); public abstract void setParentContainer(Container c);
//helper methods - initialize //helper methods - initialize

View file

@ -1,7 +1,30 @@
/*
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
with the License. You may obtain a copy of the License on the THDL web site
(http://www.thdl.org/).
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.
The Initial Developer of this software is the Tibetan and Himalayan Digital
Library (THDL). Portions created by the THDL are Copyright 2001 THDL.
All Rights Reserved.
Contributor(s): ______________________________________.
*/
package org.thdl.media;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*; import java.util.*;
public static class SmartPlayerFactory { public class SmartPlayerFactory {
/** You cannot instantiate this class. */
private SmartPlayerFactory() { }
static final String[] possiblePlayers static final String[] possiblePlayers
= {"org.thdl.media.SmartJMFPlayer", "org.thdl.media.SmartQT4JPlayer"}; = {"org.thdl.media.SmartJMFPlayer", "org.thdl.media.SmartQT4JPlayer"};

View file

@ -54,7 +54,7 @@ public class SmartQT4JPlayer extends SmartMoviePanel
private TimeBaseTimeCallBackStopper theStopper; private TimeBaseTimeCallBackStopper theStopper;
//accessors //accessors
public static String getName() { public String getName() {
return "Quicktime for Java"; return "Quicktime for Java";
} }
public void setParentContainer(Container c) { public void setParentContainer(Container c) {

View file

@ -675,14 +675,12 @@ public void setMedia(URL url) {
} }
try { try {
if (thdl_mediaplayer_property == null) Class mediaClass = Class.forName(getMediaPlayerProperty());
thdl_mediaplayer_property = getMediaPlayerProperty();
Class mediaClass = Class.forName(thdl_mediaplayer_property);
Class[] mediaArgsClass = new Class[] {Container.class, URL.class}; Class[] mediaArgsClass = new Class[] {Container.class, URL.class};
Object[] mediaArgs = new Object[] {QD.this, url}; Object[] mediaArgs = new Object[] {QD.this, url};
Constructor mediaConstructor = mediaClass.getConstructor(mediaArgsClass); Constructor mediaConstructor = mediaClass.getConstructor(mediaArgsClass);
player = (SmartMoviePanel)createObject(mediaConstructor, mediaArgs); player = (SmartMoviePanel)QD.createObject(mediaConstructor, mediaArgs);
if (null == player) throw new ClassNotFoundException("FIXME: the constructor failed.");
media = url; media = url;
mediaField.setText(media.getPath()); mediaField.setText(media.getPath());
startTimer(); startTimer();
@ -700,29 +698,6 @@ public void setMedia(URL url) {
} }
} }
public Object createObject(Constructor constructor,
Object[] arguments) {
System.out.println ("Constructor: " + constructor.toString());
Object object = null;
try {
object = constructor.newInstance(arguments);
System.out.println ("Object: " + object.toString());
return object;
} catch (InstantiationException e) {
System.out.println(e);
} catch (IllegalAccessException e) {
System.out.println(e);
} catch (IllegalArgumentException e) {
System.out.println(e);
} catch (InvocationTargetException e) {
System.out.println(e);
}
return object;
}
public Project() { public Project() {
JPanel p = new JPanel(new GridLayout(2,2)); JPanel p = new JPanel(new GridLayout(2,2));
titleField = new JTextField(); titleField = new JTextField();
@ -1785,5 +1760,35 @@ class RadioListener extends ThdlActionListener {
// project.setEditable(false); // project.setEditable(false);
} }
} }
}
/* FIXME: needs better error handling */
/** Creates an object via reflection.
* @returns nonnull on succes, null on error */
public static Object createObject(Constructor constructor,
Object[] arguments) {
System.out.println ("Constructor: " + constructor.toString());
Object object = null;
try {
object = constructor.newInstance(arguments);
System.out.println ("Object: " + object.toString());
return object;
} catch (InstantiationException e) {
System.out.println(e);
ThdlDebug.noteIffyCode();
} catch (IllegalAccessException e) {
System.out.println(e);
ThdlDebug.noteIffyCode();
} catch (IllegalArgumentException e) {
System.out.println(e);
ThdlDebug.noteIffyCode();
} catch (InvocationTargetException e) {
System.out.println(e);
System.out.println(e.getTargetException());
ThdlDebug.noteIffyCode();
}
return object;
} }
} }

View file

@ -30,11 +30,20 @@ import javax.swing.text.rtf.*;
import org.thdl.util.ThdlDebug; import org.thdl.util.ThdlDebug;
import org.thdl.util.ThdlActionListener; import org.thdl.util.ThdlActionListener;
import org.thdl.util.ThdlOptions; import org.thdl.util.ThdlOptions;
import org.thdl.tib.input.JskadKeyboardManager;
import org.thdl.tib.input.JskadKeyboardFactory;
import org.thdl.tib.input.JskadKeyboard;
import org.thdl.savant.JdkVersionHacks; import org.thdl.savant.JdkVersionHacks;
public class QDShell extends JFrame { public class QDShell extends JFrame {
/** the middleman that keeps code regarding Tibetan keyboards
* clean */
private final static JskadKeyboardManager keybdMgr
= new JskadKeyboardManager(JskadKeyboardFactory.getAllAvailableJskadKeyboards());
/** When opening a file, this is the only extension QuillDriver /** When opening a file, this is the only extension QuillDriver
cares about. This is case-insensitive. */ cares about. This is case-insensitive. */
protected final static String dotQuillDriver = ".xml"; protected final static String dotQuillDriver = ".xml";
@ -271,20 +280,6 @@ public class QDShell extends JFrame {
JMenu mediaPlayerMenu = new JMenu(messages.getString("MediaPlayer")); JMenu mediaPlayerMenu = new JMenu(messages.getString("MediaPlayer"));
for (int i = 0; i < keybdMgr.size(); i++) {
final JskadKeyboard kbd = keybdMgr.elementAt(i);
if (kbd.hasQuickRefFile()) {
JMenuItem keybdItem = new JMenuItem(kbd.getIdentifyingString());
keybdItem.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
qd.changeKeyboard(kbd);
}
});
keyboardMenu.add(keybdItem);
}
}
JMenuItem jmfItem = new JMenuItem("Java Media Framework"); JMenuItem jmfItem = new JMenuItem("Java Media Framework");
jmfItem.addActionListener(new ThdlActionListener() { jmfItem.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) { public void theRealActionPerformed(ActionEvent e) {

View file

@ -1,388 +0,0 @@
/*
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
with the License. You may obtain a copy of the License on the THDL web site
(http://www.thdl.org/).
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.
The Initial Developer of this software is the Tibetan and Himalayan Digital
Library (THDL). Portions created by the THDL are Copyright 2001 THDL.
All Rights Reserved.
Contributor(s): ______________________________________.
*/
package org.thdl.quilldriver;
import java.util.*;
import java.net.*;
import javax.media.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import org.thdl.util.ThdlDebug;
/*-----------------------------------------------------------------------*/
public class SmartJMFPlayer extends SmartMoviePanel implements ControllerListener
{
private EventListenerList listenerList = new EventListenerList();
public URL mediaURL;
private Player player = null;
private Component visualComponent = null;
private Component controlComponent = null;
private Panel panel = null;
private JPanel vPanel = null;
private Container parent = null;
private java.util.Timer timer = null;
private Time stopTime = null;
private Time pauseTime = null;
private boolean stillLoadingVideo = false;
private boolean isMediaAudio = false;
private boolean isSized = false;
private Float to = null;
/*-----------------------------------------------------------------------*/
public SmartJMFPlayer(Container p, URL sound) throws SmartMoviePanelException {
super( new GridLayout() );
parent = p;
loadMovie(sound);
}
public void loadMovie(URL sound) throws SmartMoviePanelException {
if (mediaURL != null) {
cmd_stop();
destroy();
}
mediaURL = sound;
start();
}
public void destroy() throws SmartMoviePanelException {
if (false)
throw new SmartMoviePanelException();
player.close();
}
/*-----------------------------------------------------------------------*/
private void start() {
try {
player = Manager.createPlayer(mediaURL);
player.addControllerListener(this);
} catch (javax.media.NoPlayerException e) {
System.err.println("noplayer exception");
e.printStackTrace();
ThdlDebug.noteIffyCode();
return;
} catch (java.io.IOException ex) {
System.err.println("IO exception");
ex.printStackTrace();
ThdlDebug.noteIffyCode();
return;
}
if (player != null)
player.realize();
}
/*-----------------------------------------------------------------------*/
public void displayBorders(boolean borders) throws SmartMoviePanelException
{
if (false)
throw new SmartMoviePanelException();
}
public void displayController(boolean controller) throws SmartMoviePanelException
{
if (false)
throw new SmartMoviePanelException();
}
public boolean isInitialized() {
return isSized;
}
/*-----------------------------------------------------------------------*/
public synchronized void controllerUpdate(ControllerEvent event) {
if (player == null)
return;
if (event instanceof RealizeCompleteEvent) {
System.out.println("received RealizeCompleteEvent event");
if (visualComponent == null) {
if (panel == null) {
setLayout(new GridLayout(1,1));
vPanel = new JPanel();
vPanel.setLayout( new BorderLayout() );
if ((visualComponent = player.getVisualComponent())!= null)
vPanel.add("Center", visualComponent);
else {
isMediaAudio = true;
stillLoadingVideo = false;
}
if (!stillLoadingVideo)
{
if ((controlComponent = player.getControlPanelComponent()) != null) {
if (visualComponent == null) //no video
vPanel.setPreferredSize(new Dimension(400,25));
vPanel.add("South", controlComponent);
}
}
add(vPanel);
}
}
parent.invalidate();
parent.validate();
parent.repaint();
isSized = true;
if (stillLoadingVideo)
player.start();
} else if (event instanceof StartEvent) {
StartEvent se = (StartEvent)event;
Time t = se.getMediaTime();
long longt = t.getNanoseconds();
Float from = new Float(longt);
float f = (from.floatValue() / 1000000000);
from = new Float(f);
t = player.getStopTime();
longt = t.getNanoseconds();
to = new Float(longt);
f = (to.floatValue() / 1000000000);
to = new Float(f);
if (timer != null)
{
timer.cancel();
timer = null;
}
timer = new java.util.Timer(true);
timer.schedule(new TimerTask() {
public void run() {
//this is specifically for the MPG stop time bug
if (stopTime != null)
if (player.getMediaTime().getNanoseconds() > stopTime.getNanoseconds())
player.stop();
}}, 0, 15);
} else if (event instanceof StopEvent) {
pauseTime = player.getMediaTime();
/*messy problems require messy solutions:
if the slider is present, dragging it while playing creates
a RestartingEvent, and if I set the media time here it messes up
and barely plays at all (maybe because it cancels the previously
set media time? - I don't know).
but it seems that if you press the play/pause button on the
control widget, then you need to set the media time upon stop
(probably because of problem noted below, namely that you get
weird results if you do player.start() without setting the media
time.*/
if (!(event instanceof RestartingEvent)) {
player.setMediaTime(pauseTime);
player.prefetch();
}
// player.setStopTime(Clock.RESET);
stopTime = null;
System.out.println("received StopEvent");
if (timer != null)
{
timer.cancel();
timer = null;
}
if (stillLoadingVideo)
{
System.out.println("received EndOfMediaEvent");
stillLoadingVideo = false;
player.stop();
if ((controlComponent = player.getControlPanelComponent()) != null) {
if (visualComponent == null) //no video
vPanel.setPreferredSize(new Dimension(400,25));
vPanel.add("South", controlComponent);
}
parent.invalidate();
parent.validate();
parent.repaint();
}
} else if ( event instanceof CachingControlEvent) {
CachingControlEvent e = (CachingControlEvent) event;
System.out.println("got CachingControlEvent: " + e);
if (!isMediaAudio)
stillLoadingVideo = true;
} else if (event instanceof ControllerErrorEvent) {
player = null;
System.err.println("*** ControllerErrorEvent *** " + ((ControllerErrorEvent)event).getMessage());
} else if (event instanceof PrefetchCompleteEvent) {
if (panel != null) {
panel.invalidate();
}
parent.invalidate();
parent.validate();
parent.repaint();
}
}
/*-----------------------------------------------------------------------*/
public void cmd_stop() throws SmartMoviePanelException {
if (player == null)
throw new SmartMoviePanelException("no player");
try {
player.stop();
} catch (NotRealizedError err) {
throw new SmartMoviePanelException("JMF player not realized");
}
}
public void cmd_playOn() throws SmartMoviePanelException {
if (stillLoadingVideo || player == null) {
throw new SmartMoviePanelException("no player or video still loading");
}
if (player.getState() == Controller.Started)
return;
if (pauseTime == null)
player.setMediaTime(new Time(0.0));
else
player.setMediaTime(pauseTime);
if (player.getTargetState() < Player.Started) {
player.setStopTime(Clock.RESET);
player.prefetch();
}
player.start();
}
public void cmd_playSegment(Integer from, Integer to) throws SmartMoviePanelException {
if (from == null || player == null || stillLoadingVideo)
throw new SmartMoviePanelException("no player or video still loading");
final Time startTime = new Time(from.longValue() * 1000000);
try {
if (player.getState() == Controller.Started)
player.stop();
while (player.getState() == Controller.Unrealized)
;
if (to == null) {
stopTime = null;
player.setStopTime(Clock.RESET);
} else {
stopTime = new Time(to.longValue() * 1000000);
player.setStopTime(stopTime);
}
player.setMediaTime(startTime);
player.prefetch();
player.start();
} catch(NotRealizedError err) {
throw new SmartMoviePanelException("JMF player not realized");
}
}
/*-----------------------------------------------------------------------*/
public boolean isPlaying() {
if (player == null)
return false;
if (player.getState() == Controller.Started)
return true;
return false;
}
public int getCurrentTime() {
if (player == null)
return -1;
if (player.getState() < Controller.Realized)
return -1;
long currTime = player.getMediaNanoseconds();
return new Long(currTime / 1000000).intValue();
}
public int getEndTime() {
Time t = player.getDuration();
long l = t.getNanoseconds();
return new Long(l / 1000000).intValue();
}
/*-----------------------------------------------------------------------*/
}
/*
After pause the MPEG video and playing it again it gets faster
Author: vladshtr
In Reply To: After pause the MPEG video and playing it again it gets faster
Mar 1, 2001 6:25 PM
Reply 1 of 1
The problem is in the setting the Media time.
The safety way is to always set new media time with the
following method: setMediaTime(Time time); .... if you want to
use it after
-player.stop(); used as real stop you can use setMediaTime(new
Time(0.0));
-player.stop(); used as real pause you have to use the
combination:
player.stop();
Time currentTime = player.getMediaTime();
//........
player.setMediaTime(currentTime);
player.start();
Re: (urgent) when you pause and resume, video plays at rate > 1
Author: seertenedos
In Reply To: (urgent) when you pause and resume, video plays at rate > 1
Aug 11, 2002 11:36 PM
Reply 1 of 1
I found a solution for this problem for those that are interested.
what you have to do is store the time just before you pause and then set the
time just before you play. here is a copy of my pause and play methods
// Start the player
private void play() {
if (player != null)
{
if (pauseTime != null)
{
player.setMediaTime(pauseTime);
}
if (player.getTargetState() < Player.Started)
player.prefetch();
player.start();
}
}
// Pause the player
private void pause() {
if (player != null)
pauseTime = player.getMediaTime();
player.stop();
}
that should solve your pause play problems!
> The problem is below. It seems quite a few people are
> having this problem but i have not seen a solution
> around. I really need a solution to this problem as
> the whole point of my application is that it plays
> divx and mpeg videos. At the moment i have divx
> movies playing through the mpeg demuxer as the avi one
> stuffed up the audio. I think that is the reason it
> affects both divx and mpeg. My application is due in
> one week and my client is not going to be very happy
> if this problem happens every time they pause then
> play the video.
> The player is for divx movies. If anyone knows how to
> solve this problem or how to make it so you can pause
> and resume divx movies please respond.
>
> Pause and Resume playback.
> The video plays at a high rate and there is no audio.
> Problem doesn't appear while seeking.
>
>
>
>
*/

View file

@ -1,31 +0,0 @@
package org.thdl.quilldriver;
import java.awt.*;
import java.net.*;
public abstract class SmartMoviePanel extends Panel
{
//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;
//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;
//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;
//constructor
public SmartMoviePanel(GridLayout layout)
{
super(layout);
}
}

View file

@ -1,13 +0,0 @@
package org.thdl.quilldriver;
public class SmartMoviePanelException extends Exception
{
public SmartMoviePanelException()
{
super();
}
public SmartMoviePanelException(String msg)
{
super(msg);
}
}

View file

@ -1,465 +0,0 @@
package org.thdl.quilldriver;
import java.awt.*;
import java.net.*;
import quicktime.*;
import quicktime.app.*;
import quicktime.app.display.*;
import quicktime.app.players.*;
import quicktime.app.image.*; //required for the QT4JAVA test
import quicktime.std.*;
import quicktime.std.movies.*;
import quicktime.std.movies.media.DataRef;
import quicktime.io.*;
import quicktime.app.time.*;
import quicktime.std.clocks.*;
public class SmartQT4JPlayer extends SmartMoviePanel
{
//attributes
private QTCanvas canvas; //this hands over screen real estate to
//native graphics that quicktime can control
private QTPlayer player; //this is the the client for the canvas
//In my app it will get set to a
// quicktime.app.player object
private Movie movie; //this is the content used in
//QTDrawable player's quicktime.app.player constructor
private MovieController controller;
private TimeBaseRateCallBack theMoviesRateCallback;
private TimeBaseExtremesCallBack theMoviesExtremeCallback;
private TimeBaseTimeJumpCallBack theMoviesTimeJumpCallback;
private TimeBaseTimeCallBack theMoviesTimeCallback;
private TimeBaseTimeCallBackStopper theStopper;
//accessors
public void setPlayer(QTPlayer player)
{
this.player = player;
}
public QTPlayer getPlayer()
{
return player;
}
public void setMovie(Movie movie)
{
this.movie = movie;
}
public void setMovie(URL movieURL)
{
try
{
DataRef movieDataRef = new DataRef( "file://" + movieURL.getFile() );
Movie m = new Movie();
m = m.fromDataRef( movieDataRef, StdQTConstants.newMovieActive );
setMovie(m);
getMovie().setTimeScale(1000);
}
catch(QTException qte)
{
qte.printStackTrace();
System.out.println( movieURL.toString() );
}
}
public Movie getMovie()
{
return movie;
}
public void setController(MovieController controller)
{
this.controller = controller;
}
public MovieController getController()
{
return controller;
}
public void setCanvas(QTCanvas canvas)
{
this.canvas = canvas;
}
public QTCanvas getCanvas()
{
return canvas;
}
//contract methods - initialize
public void displayBorders(boolean borders) throws SmartMoviePanelException
{
}
public void displayController(boolean controller) throws SmartMoviePanelException
{
}
public void loadMovie(URL mediaURL) throws SmartMoviePanelException
{
setMovie(mediaURL);
try
{
getCanvas().removeClient();
setController( new MovieController( getMovie() ));
getController().setKeysEnabled(true);
setPlayer(new QTPlayer( getController() ));
getCanvas().setClient( getPlayer(), true );
this.add( getCanvas() );
TimeBase theMoviesTimeBase = getMovie().getTimeBase();
// this callback is triggered when the rate of the movie changes
theMoviesRateCallback = new TimeBaseRateCallBack(theMoviesTimeBase, 1.0F, StdQTConstants.triggerRateChange);
// theMoviesRateCallback.callMeWhen();
// this callback is triggered when the movie ends
theMoviesExtremeCallback = new TimeBaseExtremesCallBack(theMoviesTimeBase, StdQTConstants.triggerAtStop);
// theMoviesExtremeCallback.callMeWhen();
// this callback is triggered when the movie starts
theMoviesExtremeCallback = new TimeBaseExtremesCallBack(theMoviesTimeBase, StdQTConstants.triggerAtStart);
// theMoviesExtremeCallback.callMeWhen();
// this callback is triggered when there is a jump in the timebase
theMoviesTimeJumpCallback = new TimeBaseTimeJumpCallBack(theMoviesTimeBase);
// theMoviesTimeJumpCallback.callMeWhen();
// this schedules the time callback once every 2 seconds
// this callback is triggered at a specific time interval
theMoviesTimeCallback = new TimeBaseTimeCallBack(theMoviesTimeBase, 1, 2, StdQTConstants.triggerTimeEither);
// theMoviesTimeCallback.callMeWhen();
//Using the Timer class you can get rescheduled properly and get callbacks at the set intervals. It uses the same callback
//mechanism of internally of the TimeCallback.
//Its recomended to use this Timer class to do callbacks , which would take care of the time base time changes and
//recscheduling of the tickle method .
Timer timer = new Timer(1, 2, new Tickler(), getMovie() );
// timer.setActive(true);
}
catch(QTException qte)
{
qte.printStackTrace();
}
}
//contract methods - control media
public void cmd_playOn() throws SmartMoviePanelException
{
try
{
getPlayer().setRate(1.0F);
}
catch(QTException qte)
{
qte.printStackTrace();
}
}
public void cmd_playSegment(Integer startTime, Integer stopTime) throws SmartMoviePanelException
{
//FIXME: need to deal with null stopTime
try
{
getPlayer().setTime( startTime.intValue() );
int value=stopTime.intValue();
TimeBase theMoviesTimeBase = getPlayer().getTimeBase();
theStopper = new TimeBaseTimeCallBackStopper(theMoviesTimeBase, 1000, value, StdQTConstants.triggerTimeEither);
theStopper.callMeWhen();
cmd_playOn();
System.out.println("Set start time to " +startTime.intValue() );
System.out.println("Set stop time " +stopTime.intValue() );
System.out.println("Current time " +getPlayer().getTime() );
System.out.println("Time Stopper's stop trigger " +theStopper.getCallTime() );
System.out.println("Player Scale: " +getPlayer().getScale() );
System.out.println("Movie Scale: " +getMovie().getTimeScale() );
}
catch (SmartMoviePanelException smpe) {}
catch (StdQTException sqte) {}
catch (QTException qte) {}
}
public void cmd_stop() throws SmartMoviePanelException
{
try
{
getPlayer().setRate(0.0F);
}
catch(QTException qte)
{
qte.printStackTrace();
}
}
//contract methods - media status
public boolean isInitialized()
{
return true;
}
public boolean isPlaying() {
return false; //FIXME
}
public int getCurrentTime()
{
try {
return getMovie().getTime();
} catch (StdQTException stqte) {
stqte.printStackTrace();
return -1;
}
}
public int getEndTime()
{
try {
return getMovie().getDuration();
} catch (StdQTException stqte) {
stqte.printStackTrace();
return -1;
}
}
//helper methods - QT4J
public void startupQTSession()
{
//Initialize a QT session and add a test image
//These three try/catch blocks come from PlayMovie.java copyright
// Apple Co. I'm using it to test that QT and QT4Java exist
try
{
if (QTSession.isInitialized() == false)
QTSession.open();
}
catch (NoClassDefFoundError er)
{
add (new Label ("Can't Find QTJava classes"), "North");
add (new Label ("Check install and try again"), "South");
}
catch (SecurityException se)
{
// this is thrown by MRJ trying to find QTSession class
add (new Label ("Can't Find QTJava classes"), "North");
add (new Label ("Check install and try again"), "South");
}
catch (Exception e)
{
// do a dynamic test for QTException
//so the QTException class is not loaded unless
// an unknown exception is thrown by the runtime
if (e instanceof ClassNotFoundException || e instanceof java.io.FileNotFoundException)
{
add (new Label ("Can't Find QTJava classes"), "North");
add (new Label ("Check install and try again"), "South");
}
else if (e instanceof QTException)
{
add (new Label ("Problem with QuickTime install"), "North");
if (((QTException)e).errorCode() == -2093)
add (new Label ("QuickTime must be installed"), "South");
else
add (new Label (e.getMessage()), "South");
}
}
try
{
setCanvas( new QTCanvas(QTCanvas.kInitialSize, 0.5F, 0.5F) );
this.add( getCanvas() );
getCanvas().setClient(ImageDrawer.getQTLogo(), true);
}
catch(QTException qte)
{
qte.printStackTrace();
}
}
public void destroy()
{
QTSession.close();
System.out.println("Clean up performed.");
}
//constructor
public SmartQT4JPlayer(Container cont, URL mediaURL)
{
super( new GridLayout() );
startupQTSession();
}
public SmartQT4JPlayer()
{
super( new GridLayout() );
startupQTSession();
}
// inner classes
/**
* This class extends the RateCallBack class and provides an execute routine
* that is invoked by the callback when the rate of the movie changes
*
*@author travis
*@created September 3, 2002
*/
public class TimeBaseRateCallBack extends RateCallBack
{
public TimeBaseRateCallBack(TimeBase tb, float rate, int flag) throws QTException
{
super(tb, rate, flag);
}
public void execute()
{
try
{
System.out.println("--- RateCallBack@ratechange---");
cancel();
//reschedule
callMeWhen();
} catch (StdQTException e)
{}
}
}
/**
* This class implements a method that is called when the movie stops
*
*@author travis
*@created September 3, 2002
*/
class TimeBaseExtremesCallBack extends quicktime.std.clocks.ExtremesCallBack
{
public TimeBaseExtremesCallBack(TimeBase tb, int flag) throws QTException
{
super(tb, flag);
}
public void execute()
{
try
{
System.out.println("--- ExtremesCallBack@stop---");
//cancel
cancel();
//reschedule
callMeWhen();
}
catch (StdQTException e)
{}
}
}
/**
* This class extends the TimeJumpCallBack class to provide a method that is
* called when the timebase of the movie changes (IE, if the user clicks in
* the movie controller)
*
*@author travis
*@created September 3, 2002
*/
class TimeBaseTimeJumpCallBack extends quicktime.std.clocks.TimeJumpCallBack
{
public TimeBaseTimeJumpCallBack(TimeBase tb) throws QTException
{
super(tb);
}
public void execute()
{
try
{
System.out.println("--- TimeJumpCallBack---");
cancel();
//reschedule
callMeWhen();
}
catch (StdQTException e)
{}
}
}
class TimeBaseTimeCallBack extends quicktime.std.clocks.TimeCallBack
{
private int callTime;
private TimeBase theTimeBase;
public void setCallTime(int time)
{
callTime=time;
value=callTime;
}
public int getCallTime()
{
return callTime;
}
public void execute()
{
try
{
System.out.println("--- TimeCallBack@triggerTimeEither--- called at:" + timeWhenCalledMsecs + "msecs");
cancel();
//reschedule
callMeWhen();
}
catch (StdQTException e)
{}
}
public TimeBaseTimeCallBack(TimeBase tb, int scale, int value, int flags) throws QTException
{
super(tb, scale, value, flags);
// setCallTime(value/1000);
setCallTime(value);
theTimeBase = tb;
}
}
class TimeBaseTimeCallBackStopper extends TimeBaseTimeCallBack
{
public void execute()
{
try
{
System.out.println("---TimeCallBackStopper--- called at:" + timeWhenCalledMsecs + "msecs");
System.out.println("---TimeCallBackStopper--- callTime is: " + getCallTime() + " msecs");
cmd_stop();
System.out.println("---TimeCallBackStopper--- Player time is: " + getPlayer().getTime() + " msecs");
System.out.println("---TimeCallBackStopper--- Movie time is: " + getMovie().getTime() + " msecs");
cancelAndCleanup();
//reschedule
//callMeWhen();
}
catch (StdQTException e) {}
catch (SmartMoviePanelException smpe) {}
}
public TimeBaseTimeCallBackStopper(TimeBase tb, int scale, int value, int flags) throws QTException
{
super(tb, scale, value, flags);
}
}
public class Tickler implements Ticklish
{
public void timeChanged(int newTime) throws QTException
{
System.out.println("* * * * Timer Class * * * timeChanged at:" + newTime);
}
public boolean tickle(float er, int time) throws QTException
{
System.out.println("* * * * Timer Class * * * tickle at:" + time);
return true;
}
}
}

View file

@ -68,6 +68,8 @@ public class Jskad extends JPanel implements DocumentListener {
private final static String enableKeypressStatusProp private final static String enableKeypressStatusProp
= "thdl.Jskad.enable.tibetan.mode.status"; = "thdl.Jskad.enable.tibetan.mode.status";
/** the middleman that keeps code regarding Tibetan keyboards
* clean */
private final static JskadKeyboardManager keybdMgr private final static JskadKeyboardManager keybdMgr
= new JskadKeyboardManager(JskadKeyboardFactory.getAllAvailableJskadKeyboards()); = new JskadKeyboardManager(JskadKeyboardFactory.getAllAvailableJskadKeyboards());