Began implementing Quicktime for Java (QT4J) option in QD. As it is, Mac OS goes to Quicktime, while Windows goes to JMF. QT player stills needs some work.

This commit is contained in:
eg3p 2002-10-15 21:22:59 +00:00
parent 7cb7f14759
commit 2ea513bab8
6 changed files with 1030 additions and 37 deletions

View file

@ -45,7 +45,6 @@ import org.thdl.util.ThdlDebug;
import org.thdl.util.ThdlActionListener;
import org.thdl.util.ThdlAbstractAction;
public class QD extends JDesktopPane {
/** When opening a file, this is the only extension QuillDriver
cares about. This is case-insensitive. */
@ -58,7 +57,7 @@ public class QD extends JDesktopPane {
protected SpeakerTable speakerTable;
//video related
protected QDPlayer player = null;
protected SmartMoviePanel player = null;
//frame related
protected JInternalFrame videoFrame = null;
@ -90,7 +89,7 @@ public class QD extends JDesktopPane {
protected TibetanDocument findDoc = null;
protected TibetanDocument replaceDoc = null;
protected URL keyboard_url = null;
protected URL keyboard_url = null;
public QD(ResourceBundle messages) {
@ -109,7 +108,7 @@ public QD(ResourceBundle messages) {
public void theRealActionPerformed(ActionEvent e) {
new TimePoint(pane, clockIcon, tcp.getOutTime());
tcp.setInTime(tcp.getOutTime().intValue());
tcp.setOutTime(player.getLastTime());
tcp.setOutTime(player.getEndTime());
}
};
@ -124,7 +123,7 @@ public QD(ResourceBundle messages) {
if (p1 == p2)
pane.setCaretPosition(pane.getCaretPosition()-1);
tcp.setInTime(tcp.getOutTime().intValue());
tcp.setOutTime(player.getLastTime());
tcp.setOutTime(player.getEndTime());
}
};
@ -216,7 +215,7 @@ private void startTimer() {
timer.schedule(new TimerTask() {
public void run()
{
if (player.cmd_isSized())
if (player.isInitialized())
{
timer.cancel();
@ -275,7 +274,7 @@ class TimePoint extends JLabel implements DragGestureListener, DragSourceListene
if (e.getButton() == MouseEvent.BUTTON1)
playSegment();
else {
SpinnerNumberModel snm1 = new SpinnerNumberModel(0, 0, player.getLastTime(), 10);
SpinnerNumberModel snm1 = new SpinnerNumberModel(0, 0, player.getEndTime(), 10);
JSpinner spinner = new JSpinner(snm1);
spinner.setPreferredSize(new Dimension(100, 40));
spinner.setValue(getTime());
@ -306,17 +305,22 @@ class TimePoint extends JLabel implements DragGestureListener, DragSourceListene
public void playSegment() {
int i=pos.getOffset();
System.out.println(String.valueOf(i));
try {
for (i++; i<doc.getLength(); i++) {
AttributeSet attr = doc.getCharacterElement(i).getAttributes();
Component comp;
if (null != (comp = StyleConstants.getComponent(attr)))
if (comp instanceof TimePoint) {
TimePoint t2 = (TimePoint)comp;
player.cmd_play(time, t2.time);
player.cmd_playSegment(time, t2.time);
return;
}
}
player.cmd_playFrom(time);
player.cmd_playSegment(time, null);
} catch (SmartMoviePanelException smpe) {
smpe.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
public void dragGestureRecognized(DragGestureEvent dge) {
Transferable transferable = new TimePointTransferable(this);
@ -429,7 +433,7 @@ class TimeCodeManager extends JPanel {
setLayout(new BorderLayout());
JPanel inPanel = new JPanel();
JButton inButton = new JButton(messages.getString("In"));
SpinnerNumberModel snm1 = new SpinnerNumberModel(0, 0, player.getLastTime(), 10);
SpinnerNumberModel snm1 = new SpinnerNumberModel(0, 0, player.getEndTime(), 10);
inSpinner = new JSpinner(snm1);
inSpinner.setValue(new Integer(0));
inSpinner.setPreferredSize(new Dimension(100, inButton.getPreferredSize().height));
@ -438,7 +442,7 @@ class TimeCodeManager extends JPanel {
inButton.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
int k = player.when();
int k = player.getCurrentTime();
if (k != -1)
setInTime(k);
}
@ -447,19 +451,24 @@ class TimeCodeManager extends JPanel {
JPanel outPanel = new JPanel();
JButton outButton = new JButton(messages.getString("Out"));
SpinnerNumberModel snm2 = new SpinnerNumberModel(0, 0, player.getLastTime(), 10);
SpinnerNumberModel snm2 = new SpinnerNumberModel(0, 0, player.getEndTime(), 10);
outSpinner = new JSpinner(snm2);
outSpinner.setValue(new Integer(player.getLastTime()));
outSpinner.setValue(new Integer(player.getEndTime()));
outSpinner.setPreferredSize(new Dimension(100, inButton.getPreferredSize().height));
outPanel.add(outButton);
outPanel.add(outSpinner);
outButton.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
int k = player.when();
int k = player.getCurrentTime();
if (k != -1) {
setOutTime(k);
try {
player.cmd_stop();
} catch (SmartMoviePanelException smpe) {
smpe.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
}
});
@ -470,8 +479,14 @@ class TimeCodeManager extends JPanel {
public void theRealActionPerformed(ActionEvent e) {
Integer in = getInTime();
Integer out = getOutTime();
if (out.intValue() > in.intValue())
player.cmd_play(in, out);
if (out.intValue() > in.intValue()) {
try {
player.cmd_playSegment(in, out);
} catch (SmartMoviePanelException smpe) {
smpe.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
}
});
JPanel ps = new JPanel();
@ -483,14 +498,26 @@ class TimeCodeManager extends JPanel {
playButton.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
if (player != null)
player.cmd_play();
if (player != null) {
try {
player.cmd_playOn();
} catch (SmartMoviePanelException smpe) {
smpe.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
}
});
pauseButton.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
if (player != null)
if (player != null) {
try {
player.cmd_stop();
} catch (SmartMoviePanelException smpe) {
smpe.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
}
});
*/
@ -578,8 +605,13 @@ public void setMedia(File f) {
media = f;
mediaField.setText(media.getPath());
if (player != null) {
try {
player.cmd_stop();
player.destroy();
} catch (SmartMoviePanelException smpe) {
smpe.printStackTrace();
ThdlDebug.noteIffyCode();
}
videoFrame.getContentPane().remove(player);
videoFrame.getContentPane().invalidate();
videoFrame.getContentPane().validate();
@ -597,13 +629,33 @@ public void setMedia(File f) {
URL url = f.toURL();
if (player != null) {
try {
player.cmd_stop();
player.destroy();
} catch (SmartMoviePanelException smpe) {
smpe.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
//if user properties opt for qt4j instead of jmf, then load qt4j instead
String os = System.getProperty("os.name").toLowerCase();
try {
if (os.indexOf("windows") != -1) {
player = new SmartJMFPlayer(QD.this, url);
} else if (os.indexOf("mac") != -1) {
player = new SmartQT4JPlayer();
player.loadMovie(url);
}
player = new QDPlayer(QD.this, url);
media = f;
mediaField.setText(media.getPath());
startTimer();
} catch (SmartMoviePanelException smpe) {
smpe.printStackTrace();
ThdlDebug.noteIffyCode();
}
} catch (MalformedURLException murle) {
murle.printStackTrace();
ThdlDebug.noteIffyCode();
@ -893,6 +945,7 @@ if (keyboard_url != null) {
dp.registerKeyboard();
// project.tName.setupKeyboard();
// project.tTask.setupKeyboard();
sharedDP.setupKeyboard();
sharedDP2.setupKeyboard();

View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:jskad="xalan://org.thdl.tib.text">
<xsl:output method="html"/>
<xsl:template match="qd">
<html>
<head>
<style>
<xsl:value-of select="jskad:TibetanHTML.getStyles(28)" disable-output-escaping="yes"/>
</style>
</head>
<body>
<xsl:apply-templates select="metadata/title" />
<xsl:apply-templates select="text" />
<xsl:apply-templates select="metadata/workhistory" />
</body>
</html>
</xsl:template>
<xsl:template match="title">
<xsl:value-of select="." />
<p />
</xsl:template>
<xsl:template match="text">
<xsl:apply-templates select="node()" />
</xsl:template>
<xsl:template match="who">
<p />
<xsl:variable name="idvar" select="@id" />
<xsl:variable name="name" select="../../metadata/speakers/speaker[@iconid=$idvar]" />
<u><xsl:value-of select="jskad:TibetanHTML.getHTML($name)" disable-output-escaping="yes"/></u>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="jskad:TibetanHTML.getIndentedHTML(.)" disable-output-escaping="yes"/>
</xsl:template>
<xsl:template match="workhistory">
<p />
<b>Work History</b>
<p/>
<table width="100%" border="1">
<tr>
<th>Name</th>
<th>Task</th>
<th>Start Time</th>
<th>Duration</th>
</tr>
<xsl:apply-templates select="work"/>
</table>
</xsl:template>
<xsl:template match="work">
<tr>
<td><xsl:value-of select="name" disable-output-escaping="yes"/></td>
<td><xsl:value-of select="task" disable-output-escaping="yes"/></td>
<td><xsl:value-of select="start" /></td>
<td><xsl:value-of select="duration" /> minutes</td>
</tr>
</xsl:template>
</xsl:stylesheet>

View file

@ -0,0 +1,379 @@
/*
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.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 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

@ -0,0 +1,30 @@
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 int getCurrentTime();
public abstract int getEndTime();
//helper methods - cleanup
public abstract void destroy() throws SmartMoviePanelException;
//constructor
public SmartMoviePanel(GridLayout layout)
{
super(layout);
}
}

View file

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

View file

@ -0,0 +1,451 @@
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
{
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 int getCurrentTime()
{
return 0;
}
public int getEndTime()
{
return 0;
}
//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;
}
}
}