/* * @(#)MediaPlayer.java 1.22 02/08/21 * * Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved. */ // @version 1.0 // Last Updated: 02/19/99 // Notes: N/A package javax.media.bean.playerbean; import java.applet.Applet; import java.awt.*; import java.awt.event.*; import java.lang.String; import java.lang.reflect.*; import java.net.*; import java.io.*; import java.util.Properties; import java.util.Vector; import javax.media.*; import javax.media.protocol.*; import java.beans.*; import javax.media.rtp.*; import javax.media.format.*; import javax.media.rtp.event.*; import java.applet.AppletContext; /** * <CODE>MediaPlayer</CODE> encapsulates a player in a * JavaBeans<sup><font size="-2">TM</sup></font> component. * <CODE>MediaPlayer</CODE> implements the <CODE>Player</CODE> and <CODE>Externalizable</CODE> * interfaces. * <p> * A <CODE>MediaPlayer</CODE> can be used as a * full-featured <CODE>Player</CODE> with either the default <CODE>Player</CODE> controls or * custom controls. * * <h3><CODE>MediaPlayer</CODE> Properties</h3> * <p> * The following bean properties are supported by <CODE>MediaPlayer</CODE>: * <ul> * <li>loop: Indicates whether or not the media will be played repeatedly. * * <li>media location: The location of the media to be played. The location can be either an * absolute address such as <CODE>http://xena/demo/media/Sample1.mov</CODE> * or an address relative to the codebase address such as <CODE>media/Sample1.mov</CODE> * <li>name: The name of this <CODE>MediaPlayer</CODE>. * <li>size and position: The size and position of this * <CODE>MediaPlayer</CODE>. * <li>volume: The audio volume as a number from 0 to 5, where 0 is muted * and 5 is the loudest possible volume. The default value is 3. * * <li>show control panel: Indicates whether or not the video control panel is * displayed. * <li>show caching control: Indicates whether or not the caching control is displayed. * The caching control shows the download progress. * * <li>fixed aspect ratio: Indicates whether or not the aspect ratio of the video * is maintained when the visual component is resized. * </ul> * <p> * Two additional properties can be set. These are not bean properties, but provide * additional control over the presentation: * <ul> * <li>ZoomLevel: Can be set through the popup menu and via set and get methods. * (Click the right mouse button over the media to bring up the popup menu.) * * <li>MediaLocationVisible: Can be set through get and set methods. The media location * is not editable during runtime. * * <h3>Invoking <CODE>MediaPlayer</CODE></h3> * <p> * You can instantiate MediaPlayer directly or using a bean-enabled IDE tool such as NetObjects * BeanBuilder. To instantiate <CODE>MediaPlayer</CODE> directly: * * <pre> * ClassLoader cl = this.getClass().getClassLoader(); * MediaPlayer pb = (MediaPlayer)Beans.instantiate(cl, * "javax.media.bean.playerbean.MediaPlayer"); * </pre> * */ public class MediaPlayer extends Container implements Player,Externalizable { private PropertyChangeSupport changes = new PropertyChangeSupport(this); // the media location the user specified. It can be absolute or relative // address. private String urlString = ""; private MediaLocator mrl; private URL url; private AppletContext mpAppletContext = null; //applet context of container //Should the Player's control panel be visible? private boolean panelVisible = true; //Should the Player's caching control panel be visible? private boolean cachingVisible = false; //Should maintain aspect ratio? private boolean fixedAspectRatio = true; //Should the user be able to scale the video? private boolean fitVideo = true; //Should the video loop after it has reached the end? private boolean looping = true; //Private variables: //The actual JMF Player transient Player player = null; //The panel which contains the player components: [visual component, // control panel] transient Panel panel; // the panel which contains the visual component of a player. transient Panel vPanel; //the panel for control component and url transient Panel newPanel; //And the visual component itself transient Component visualComponent; //and the controlComponent transient Component controlComponent; //and the cachingControl progress bar component transient Component cachingComponent; //How high is the controlPanel private transient int controlPanelHeight = 0; //How high is the urlField private transient int urlFieldHeight = 0; //The preferredHeight private int preferredHeight; //And PreferredWidth private int preferredWidth; //And, of course, the current state of the player private int state; // a set of MediaPlayers, which are placed under this bean's control private Vector controlListeners = new Vector(); //popup menu for controlling the size PopupMenu zoomMenu = null; //code base of Applet private URL mpCodeBase = null; protected transient GainControl gainControl; // external for the current volume level protected transient String curVolumeLevel = MediaPlayerResource.getString("THREE"); // internal presentation for the current volume level protected transient float curVolumeValue = 0.6f; // external presentation for the current zoom level protected transient String curZoomLevel = MediaPlayerResource.getString("SCALE_NORMAL"); // internal presentation for the current zoom level protected transient float curZoomValue = 1.0f; transient protected Time mediaTime; private InternalControllerAdapter selfListener; //media length for caching control private long contentLength=0; private boolean fixtedFirstTime=true; private boolean displayURL = false; //if popup menu is active private boolean isPopupActive = true; //The widget displaying the media location for the player private transient TextField urlName; private transient visualMouseAdapter mouseListen; /** * * InternalControllerAdapter: * Inner class to catch player event * */ class InternalControllerAdapter extends ControllerAdapter { private MediaPlayer thisBean; /** * * Constructs an <CODE>InternalControllerAdapter</CODE>. * @param b Instance of <CODE>MediaPlayer</CODE> bean * */ public InternalControllerAdapter(MediaPlayer b) { super(); thisBean=b; } /** * * Replaces the URL that is invoked when a hot * link to a new URL is triggered. * * @param ReplaceURLEvent A <CODE>ControllerEvent</CODE> that indicates that the * mediaLocation has been changed. * */ public void replaceURL(Object e) { debug("ReplaceURLEvent "); URL retobj=null; try { Class cls = Class.forName("com.ibm.media.ReplaceURLEvent"); Method meth = cls.getMethod("getURL",null); retobj = (URL)meth.invoke(e, null); } catch (Throwable t) { System.err.println(t); } setMediaLocation(retobj.toExternalForm()); thisBean.start(); } /** * * Displays the html document which is invoked when a * hotlink to a html is triggered in a mvr file * * @param ShowDocumentEvent a <CODE>ControllerEvent</CODE> that indicates that * URL to show in a web page. * */ public void showDocument(Object e) { debug("ShowDocumentEvent "); initSetCodeBase(); URL retURL=null; String retContext=null; try { Class cls = Class.forName("com.ibm.media.ShowDocumentEvent"); Method meth = cls.getMethod("getURL",null); retURL = (URL)meth.invoke(e, null); meth = cls.getMethod("getString",null); retContext = (String)meth.invoke(e, null); } catch (Throwable t) { System.err.println(t); } if (mpAppletContext !=null) { mpAppletContext.showDocument(retURL,retContext); } } /** * * Gets the current state. * * @param TransitionEvent A <CODE>ControllerEvent</CODE> that indicates that a * <CODE>Controller</CODE> has changed state. * */ public void transition(TransitionEvent e) { debug("TransitionEvent "+e); state = e.getCurrentState(); } /** * * When the player is Realized, it calls doRealize * internal function to get the visual, gain, control components and * add them to the panel of bean. If fixedAspectRatio is set, it will * check if Bean has more space to expand the visual component and calculate * the * * @param RealizeCompleteEvent A <CODE>ControllerEvent</CODE> that indicates a * <CODE>Controller</CODE> has finished realizing. */ public void realizeComplete(RealizeCompleteEvent e) { debug(" Event: RealizeComplete"); doRealize(); } /** * * When the player is Prefetched, removes the progress bar, * sets the size, and sets the visual component visible * * @param prefetchCompleteEvent A <CODE>ControllerEvent</CODE> that indicates a * <CODE>Controller</CODE> has finished Prefetching. */ public void prefetchComplete(PrefetchCompleteEvent e) { debug(" Event:prefetchComplete"); //doPrefetch(); } /** * * When player format changes, remove the old visual component * then create the new one. * * @param FormatChangeEvent A <CODE>ControllerEvent</CODE> that indicates a * <CODE>Controller</CODE> changes format. */ public void formatChange(FormatChangeEvent e) { debug(" formatChangeevent"); Component oldVisualComp = visualComponent; if (player==null) { Fatal(MediaPlayerResource.getString("SHOULD NOT OCCUR")); System.exit(-1); } if (( visualComponent = player.getVisualComponent())!= null) { if (oldVisualComp !=visualComponent) { if (oldVisualComp !=null) { oldVisualComp.remove(zoomMenu); vPanel.remove(oldVisualComp); panel.remove(vPanel); Component oldComp = controlComponent; if ((oldComp != null) && (newPanel != null)) { newPanel.remove(oldComp); if (displayURL == true) newPanel.remove(urlName); panel.remove(newPanel); } } doRealize(); } else if ((getMediaLocation().endsWith("mvr"))|| (getMediaLocation().endsWith("MVR"))) { // calculateSize(); zoomTo((float)1.0); //mvr doesn't zoom so not calculation needed // zoomTo(curZoomValue); } } else { Component oldComp = controlComponent; if ((( controlComponent = player.getControlPanelComponent()) != null) && (isControlPanelVisible())) { if ( oldComp != controlComponent) { if (oldComp!=null) { newPanel.remove(oldComp); if (displayURL==true) newPanel.remove(urlName); panel.remove(newPanel); } doRealize(); } } else { //new control comp is null if ((oldVisualComp !=null)&&(vPanel!=null)) { oldVisualComp.remove(zoomMenu); vPanel.remove(oldVisualComp); panel.remove(vPanel); } } } } /** * * When the player is started. * * @param StartEvent A <CODE>ControllerEvent</CODE> that indicates a <CODE>Controller</CODE> * has entered into the <EM>Started</EM> state */ public void start(StartEvent e) { debug(" Event:StartEvent "); } /** * * When the player reach the end of media, if loop is set, * restart it. * @param EndOfMediaEvent A <CODE>ControllerEvent</CODE> that indicates a <CODE>Controller</CODE> * has reached the end of its media and is stopping. * */ public void endOfMedia(EndOfMediaEvent e) { // We've reached the end of the media; rewind and // start over debug(" Event:EndofMediaEvent"); if (isPlayBackLoop()) { synchronized (this) { if (player==null) { Fatal(MediaPlayerResource.getString("SHOULD NOT OCCUR")); System.exit(-1); } if ( player != null ) player.setMediaTime(new Time(0)); if ( player != null ) player.start(); } } } /** * * When the player has an error condition occur, log the * error message. * @param controllerErrorEvent A <CODE>ControllerEvent</CODE> that indicates a * <CODE>Controller</CODE> error condition occurs that will cause * a <CODE>Controller</CODE> to cease functioning. * */ public void controllerError(ControllerErrorEvent e) { // Tell TypicalPlayerApplet.start() to call it a day debug(" Event:ControllerErrorEvent"); player = null; Fatal(e.getMessage()); } /** * * When the input video has changed in size, recalculate, * and redraw. * @param SizeChangeEvent A <CODE>ControllerEvent</CODE> that indicates the * input video has changed in size and the video renderer needs * to be resized to specified size * */ public void sizeChange(SizeChangeEvent e) { debug(" Event:SizeChangeEvent"); int newPanelHeight =0; if ((controlComponent != null) && isControlPanelVisible()) newPanelHeight= controlPanelHeight; if ((urlName!=null) &&(isMediaLocationVisible())) newPanelHeight += urlFieldHeight; if (visualComponent != null){ visualComponent.setSize(e.getWidth(), e.getHeight()); preferredHeight = visualComponent.getPreferredSize().height; preferredWidth = visualComponent.getPreferredSize().width; } if (panel != null) { if (vPanel != null) { vPanel.setBounds(0, 0, e.getWidth(), e.getHeight()-newPanelHeight ); vPanel.validate(); } panel.setBounds(0, 0, e.getWidth(), e.getHeight()); panel.validate(); } invalidate(); validate(); } /** * * When the caching event generated, if no progress * bar, then create it, if download completed, remove * the progress bar. * @param cachingControlEvent A <CODE>ControllerEvent</CODE> that indicates the * caching state change. * */ public void cachingControl(CachingControlEvent e) { debug(" Event: CachingControl"); if (isCachingControlVisible() == true) { CachingControl cc = e.getCachingControl(); long contentLength=cc.getContentLength(); if ((cc != null && cachingComponent == null)&& (contentLength!=CachingControl.LENGTH_UNKNOWN)) { cachingComponent = cc.getControlComponent(); if (cachingComponent == null) cachingComponent = cc.getProgressBarComponent(); if (cachingComponent != null) { panel.add("South",cachingComponent); Dimension prefSize = cachingComponent.getPreferredSize(); cachingComponent.setBounds(0, 0, prefSize.width, prefSize.height); panel.setSize(prefSize.width, prefSize.height); panel.validate(); } } else { if (cc.getContentProgress()==contentLength){ if (cachingComponent!=null) { panel.remove(cachingComponent); validate(); } } } } } } /** * Constructs a MediaPlayer with its main panel preparing for * caching control events and the following visual display. * */ public MediaPlayer() { super(); setLayout(null); if (panel == null) { panel = new Panel(); panel.setLayout(new BorderLayout()); panel.setVisible(false); add("Center",panel); } } /** * * doRealize(): internal function to get the visual, gain, control components and * add them to the panel of bean. If fixedAspectRatio is set, it will * check if Bean has more space to expand the visual component and calculate * the zoom factor. * */ private synchronized void doRealize() { debug("in doRealize"); if (player==null) { Fatal(MediaPlayerResource.getString("SHOULD NOT OCCUR")); System.exit(-1); } gainControl = player.getGainControl(); if (gainControl !=null) { float re=gainControl.setLevel(curVolumeValue); } if (( visualComponent = player.getVisualComponent())!= null) { vPanel = new Panel(); vPanel.setLayout( new BorderLayout() ); panel.setVisible(false); visualComponent.setVisible(false); vPanel.add("Center", visualComponent); panel.add("Center", vPanel); addComponentListener(new visualComponentAdapter(this)); addPopupMenu(visualComponent); setPopupActive(); } newPanel=new Panel(); newPanel.setLayout(new BorderLayout()); panel.add("South",newPanel); urlName = new TextField(10); urlName.setEditable(false); if (displayURL==true) { urlName.setText(urlString); newPanel.add("South",urlName); } if ((( controlComponent = player.getControlPanelComponent()) != null)&& (isControlPanelVisible())) { controlComponent.setVisible(false); newPanel.add("North",controlComponent); } calculateSize(); if (visualComponent == null) { if (controlComponent !=null) panel.setSize(controlComponent.getPreferredSize().width, controlPanelHeight+urlFieldHeight ); else panel.setSize(100,urlFieldHeight); } showVisual(); } private void calculateSize() { if ( player == null ) return; debug("claculateSize"); if (( visualComponent = player.getVisualComponent())!= null) { // visualComponent.setSize(visualComponent.getPreferredSize()); preferredHeight =visualComponent.getPreferredSize().height; preferredWidth =visualComponent.getPreferredSize().width; } if (((( controlComponent = player.getControlPanelComponent()) != null)&& (isControlPanelVisible()))||(displayURL==true)) { if ((controlComponent!=null)&& (isControlPanelVisible())) { controlPanelHeight = controlComponent.getPreferredSize().height; preferredHeight +=controlPanelHeight; if (preferredWidth ==0) preferredWidth = 320; } if (displayURL==true) { urlFieldHeight = urlName.getPreferredSize().height; preferredHeight +=urlFieldHeight; } } if (visualComponent != null) { Dimension vSize = visualComponent.getPreferredSize(); int totalHeight=0; if (controlComponent != null) { totalHeight+=controlComponent.getPreferredSize().height; } if (displayURL==true) { totalHeight +=urlName.getPreferredSize().height; } if (( fixedAspectRatio==true) && (curZoomValue == 1.0)) { //compare the ratio of parent and panel, and get the smaller number if ((vSize.width!=0) &&(vSize.height!=0)) { if (((float)getSize().width/(float)vSize.width) >= ((float)(getSize().height-totalHeight)/ (float)(vSize.height))) { curZoomValue = ((float)(getSize().height-totalHeight)/ (float)(vSize.height)); } else { curZoomValue = ((float)getSize().width/vSize.width); } } if (curZoomValue <0.5) curZoomValue=1; } if (newPanel !=null) newPanel.setSize(visualComponent.getPreferredSize().width, controlPanelHeight+urlFieldHeight); } } private synchronized void showVisual() { //debug(" doPrefetch"); if (cachingComponent!=null) { panel.remove(cachingComponent); validate(); } if ((visualComponent!=null) && ((fixedAspectRatio==true) || (fixtedFirstTime==false))) { zoomTo(curZoomValue); } else { panel.setSize(getSize()); } panel.setVisible(true); if (visualComponent != null) { visualComponent.setVisible(true); } if ((controlComponent != null)&& (isControlPanelVisible())) { controlComponent.setVisible(true); } panel.validate(); validate(); } /** * initSetCodeBase(): * set codebase for relative media location. * */ private void initSetCodeBase() { if (mpCodeBase!=null) return; Container p = getParent(); while (p!=null) { if (p instanceof Applet) break; p = p.getParent(); } if (p!=null) { setCodeBase(((Applet)p).getCodeBase()); mpAppletContext = ((java.applet.Applet) p).getAppletContext(); } } // MediaPlayer property methods: /** * Gets the value of the media location property for this <CODE>MediaPlayer</CODE>. * * @return A <CODE>String</CODE> that contains the media location. * */ public String getMediaLocation() { if (mrl !=null) { return mrl.toString(); } else { return urlString; } } /** * * Gets a <CODE>MediaLocator</CODE> for this <CODE>MediaPlayer</CODE> * that corresponds to the specified <CODE>String</CODE>. * * @param filename A <CODE>String</CODE> that contains the media name * from which to create the <CODE>MediaLocator</CODE>. * @return A <CODE>MediaLocator</CODE> that corresponds to the specified <CODE>String</CODE>. * */ protected MediaLocator getMediaLocator(String filename) { MediaLocator localml = null; if (filename.regionMatches(true, 0, "<codebase>", 0, 10)) { try { if (mpCodeBase == null) initSetCodeBase(); localml = new MediaLocator( new URL(mpCodeBase, filename.substring(11))); } catch (java.net.MalformedURLException e) { if (mpCodeBase != null ) { log(MediaPlayerResource.getString("NO IMAGE:BAD_URL")+ filename+" " + mpCodeBase); urlString = " "; } return null; } } else { localml = new MediaLocator(filename); } return localml; } /** * Sets the media location property for this <CODE>MediaPlayer</CODE>. * This property specifies the location of the media file to be * presented by the <CODE>MediaPlayer</CODE>. * If a <CODE>Player</CODE> already exists for this <CODE>MediaPlayer</CODE>, * this method stops that <CODE>Player</CODE> and releases all * of the resources it is using. Then a new <CODE>Player</CODE> is created to * present the specified media file. * All controller listeners registered for the old * <CODE>Player</CODE> are added to the listener list of the new <CODE>Player</CODE>. * * @param location A <CODE>String</CODE> that contains the location of the media file. * */ public void setMediaLocation(String location) { try { String old = ""; if (mrl !=null) { old = mrl.toExternalForm(); if (panel != null) panel.removeAll(); if (player != null) { player.stop(); player.close(); panel.validate(); if (controlListeners.contains(selfListener)) controlListeners.removeElement(selfListener); } } urlString = location; if ((mrl = getMediaLocator(location))==null) { //urlString = ""; return; } try { player = javax.media.Manager.createPlayer(mrl); } catch (Exception e) { player = null; urlString = " "; changes.firePropertyChange("mediaLocation", location, old); Fatal(MediaPlayerResource.getString("UNABLE_CREATE_PLAYER")+e); return; } if (player==null) { return; } if (urlName !=null) { urlName.setText(urlString); urlName.setFont(getFont()); } player.addControllerListener(selfListener=new InternalControllerAdapter(this)); if (!controlListeners.isEmpty()) { for (int i=0;i<controlListeners.size();i++) player.addControllerListener( (ControllerListener)controlListeners.elementAt(i)); } changes.firePropertyChange("mediaLocation", old, location); } catch (Exception e) { mrl = null; e.printStackTrace(); Fatal(MediaPlayerResource.getString("UNABLE_CREATE_PLAYER")+e); return; } } /** * Sets the <CODE>MediaLocator</CODE> for this <CODE>MediaPlayer</CODE>. This * method creates a <CODE>Player</CODE> for the specified <CODE>MediaLocator</CODE>. * If a <CODE>Player</CODE> already exists for this <CODE>MediaPlayer</CODE>, * this method stops that <CODE>Player</CODE> and releases all * of the resources it is using. Then a new <CODE>Player</CODE> is created with * the specified <CODE>MediaLocator</CODE>. * All controller listeners registered for the old * <CODE>Player</CODE> are added to the listener list of the new <CODE>Player</CODE>. * * @param locator A <CODE>MediaLocator</CODE> that identifies the media file to be * presented by the <CODE>MediaPlayer</CODE>. * */ public void setMediaLocator(MediaLocator locator) { try { debug("setMediaLocator"); if (locator != null) { if (mrl !=null) { if (panel != null) panel.removeAll(); if (player != null) { player.stop(); player.close(); if (controlListeners.contains(selfListener)) controlListeners.removeElement(selfListener); } } } else return; try { player = javax.media.Manager.createPlayer(locator); } catch (NoPlayerException e) { player = null; urlString = " "; Fatal(MediaPlayerResource.getString("UNABLE_CREATE_PLAYER")+e); return; } catch (java.io.IOException e) { player = null; urlString = " "; Fatal(MediaPlayerResource.getString("IO_EXCEPTION")+e); return; } if (player==null) { return; } urlString = locator.toExternalForm(); mrl = locator; if (urlName !=null) { urlName.setText(urlString); urlName.setFont(getFont()); } player.addControllerListener(selfListener=new InternalControllerAdapter(this)); if (!controlListeners.isEmpty()) { for (int i=0;i<controlListeners.size();i++) player.addControllerListener( (ControllerListener)controlListeners.elementAt(i)); } } catch (Exception e) { url = null; e.printStackTrace(); Fatal(MediaPlayerResource.getString("UNABLE_CREATE_PLAYER")+e); return; } } /** * Sets the <CODE>DataSource</CODE> for this <CODE>MediaPlayer</CODE>. This * method creates a <CODE>Player</CODE> for the specified <CODE>DataSource</CODE>. * If a <CODE>Player</CODE> already exists for this <CODE>MediaPlayer</CODE>, * this method stops that <CODE>Player</CODE> and releases all * of the resources it is using. Then a new <CODE>Player</CODE> is created with * the specified <CODE>DataSource</CODE>. * All controller listeners registered for the old * <CODE>Player</CODE> are added to the listener list of the new <CODE>Player</CODE>. * * @param ds A <CODE>DataSource</CODE> that identifies the media file to be * presented by the <CODE>MediaPlayer</CODE>. * */ public void setDataSource(DataSource ds) { try { debug("setDataSource"); if (ds != null) { if (panel != null) panel.removeAll(); if (player != null) { player.stop(); if (controlListeners.contains(selfListener)) controlListeners.removeElement(selfListener); } } if (urlName !=null) { if (ds.getLocator()!=null) urlName.setText(ds.getLocator().toExternalForm()); else urlName.setText(""); urlName.setFont(getFont()); } try { player = javax.media.Manager.createPlayer(ds); } catch (Exception e) { player = null; urlString = " "; Fatal(MediaPlayerResource.getString("UNABLE_CREATE_PLAYER")+e); return; } if (player==null) { return; } if (ds.getLocator()!=null) urlString = ds.getLocator().toExternalForm(); else urlString = ""; player.addControllerListener(selfListener=new InternalControllerAdapter(this)); if (!controlListeners.isEmpty()) { for (int i=0;i<controlListeners.size();i++) player.addControllerListener( (ControllerListener)controlListeners.elementAt(i)); } } catch (Exception e) { mrl = null; e.printStackTrace(); Fatal(MediaPlayerResource.getString("UNABLE_CREATE_PLAYER")+e); return; } } /** * Specifies an existing <CODE>Player</CODE> to use to present media * for this <CODE>MediaPlayer</CODE>. * If a <CODE>Player</CODE> already exists for this <CODE>MediaPlayer</CODE>, * this method stops that <CODE>Player</CODE> and releases all * of the resources it is using. * All controller listeners registered for the old * <CODE>Player</CODE> are added to the listener list of the new <CODE>Player</CODE>. * * @param newPlayer The <CODE>Player</CODE> to use to present media data for * this <CODE>MediaPlayer</CODE>. * */ public void setPlayer(Player newPlayer) { debug("setPlayer"); if (newPlayer == null) return; if (newPlayer != null) { if (panel != null) panel.removeAll(); if (player != null) { player.stop(); if (controlListeners.contains(selfListener)) controlListeners.removeElement(selfListener); } } player=newPlayer; urlString = ""; player.addControllerListener(selfListener=new InternalControllerAdapter(this)); switch(player.getState()) { case (Prefetched): debug("player state prefetched "); break; case (Prefetching): debug("player state prefetching "); break; case (Realized): debug("player state Realized "); break; case (Realizing): debug("player state Realizing"); break; case (Started): debug("player state started "); break; case (Unrealized): debug("player state Unrealized "); break; } if ((player.getState()==Realized) || (player.getState()==Prefetching)) doRealize(); if ((player.getState()==Prefetched) || (player.getState()==Started)) { doRealize(); //doPrefetch(); } if (!controlListeners.isEmpty()) { for (int i=0;i<controlListeners.size();i++) player.addControllerListener( (ControllerListener)controlListeners.elementAt(i)); } } /** * * Gets the loop property for this <CODE>MediaPlayer</CODE>. This property indicates * whether the <CODE>MediaPlayer</CODE> should play the media stream * repeatedly or stop when the end of media is reached. * * @return <CODE>true</CODE> if loop is enabled, <CODE>false</CODE> if the media stream * is to be played only once. * */ public boolean getPlaybackLoop() { return looping; } /** * * Sets the loop property for this <CODE>MediaPlayer</CODE>. This property indicates * whether the <CODE>MediaPlayer</CODE> should play the media stream * repeatedly or stop when the end of media is reached. * * @param val The boolean value for the loop property. Specify <CODE>true</CODE> * to enable looping, <CODE>false</CODE> if the media stream * is to be played only once. * */ public void setPlaybackLoop(boolean val) { boolean old = looping; looping = val; changes.firePropertyChange("playbackLoop", new Boolean(old), new Boolean(looping)); } /** * * Gets the loop property for this <CODE>MediaPlayer</CODE>. This property indicates * whether the <CODE>MediaPlayer</CODE> should play the media stream * repeatedly or stop when the end of media is reached. * * @return <CODE>true</CODE> if loop is enabled, <CODE>false</CODE> if the media stream * is to be played only once. * */ public boolean isPlayBackLoop() { return looping; } /** * * Sets the zoom property for this <CODE>MediaPlayer</CODE>. This property specifies * a scale factor for the visual components. When <CODE>zoom</CODE> is called, the * visual components are resized accordingly. * * @param scale A <CODE>String</CODE> that specifies the zoom factor. Possible values are * <CODE>Scale 1:2</CODE>, <CODE>Scale 1:1</CODE>, <CODE>Scale 2:1</CODE>, * and <CODE>Scale 4:1</CODE>. * */ public void setZoomTo(String scale) { debug("setZoomTo"); curZoomLevel = scale; if (scale.trim().equals(MediaPlayerResource.getString("1:2"))) { curZoomValue = 0.5f; } else if (scale.trim().equals(MediaPlayerResource.getString("1:1"))) { curZoomValue = 1.0f; } else if (scale.trim().equals(MediaPlayerResource.getString("2:1"))) { curZoomValue = 2.0f; } else if (scale.trim().equals(MediaPlayerResource.getString("4:1"))) { curZoomValue = 4.0f; } fixtedFirstTime=false; zoomTo(curZoomValue); } /** * * Gets the zoom property for this <CODE>MediaPlayer</CODE>. This property specifies * a scale factor for the visual components. * * @return A <CODE>String</CODE> that specifies the zoom factor. Possible values are * <CODE>Scale 1:2</CODE>, <CODE>Scale 1:1</CODE>, <CODE>Scale 2:1</CODE>, * and <CODE>Scale 4:1</CODE>. * */ public String getZoomTo() { return this.curZoomLevel; } /** * * Gets the height of the control <CODE>Component</CODE> for this <CODE>MediaPlayer</CODE>. * * @return The control <CODE>Component</CODE> height as an integer. * */ public int getControlPanelHeight() { if (isControlPanelVisible()) return controlPanelHeight; else return 0; } /** * * Gets the height of the media-location text field for this <CODE>MediaPlayer</CODE>. * * @return The height of the media location text field as an integer. * */ public int getMediaLocationHeight() { if (isMediaLocationVisible()) return urlFieldHeight; else return 0; } /** * * Sets the audio volume property for this <CODE>MediaPlayer</CODE>. * The volume can range from zero to five, where zero is silence * and five is the maximum volume. * * @param volumeString A <CODE>String</CODE> that represents the audio volume. * Possible values are "0", "1", "2", "3", "4", or "5". * */ public void setVolumeLevel(String volumeString) { debug("in setVolumeLevel"); if (volumeString == null) { return; } String old = curVolumeLevel; int level = Integer.parseInt(volumeString); curVolumeLevel = volumeString; curVolumeValue = level * 0.2f; if (gainControl != null) gainControl.setLevel(curVolumeValue); changes.firePropertyChange("volumeLevel", old, curVolumeLevel); } /** * * Gets the audio volume property for this <CODE>MediaPlayer</CODE>. * The volume can range from zero to five, where zero is silence * and five is the maximum volume. * @return A <CODE>String</CODE> that represents the audio volume. * Possible values are "0", "1", "2", "3", "4", or "5". * */ public String getVolumeLevel() { return this.curVolumeLevel; } /** * * Gets the MediaLocationVisible property for this <CODE>MediaPlayer</CODE>. * * @return <CODE>true</CODE> if the media location is visible at runtime, * <CODE>false</CODE> if it is not. * */ public boolean isMediaLocationVisible() { return displayURL; } /** * * Sets the MediaLocationVisible property for this <CODE>MediaPlayer</CODE>. * * @param val A boolean that indicates whether or not the media location is visible. * Set to <CODE>true</CODE> if the media location is visible at runtime, * <CODE>false</CODE> if it is not. * */ public void setMediaLocationVisible(boolean val) { if (displayURL != val) { if (urlName !=null) { if (val) { urlName.setText(urlString); newPanel.add("South",urlName); } else { newPanel.remove(urlName); } } panel.validate(); validate(); displayURL = val; } } /** * * Gets the control panel visibility property for this <CODE>MediaPlayer</CODE>. * This property indicates whether or not the control panel is visible at runtime. * * @return <CODE>true</CODE> if the control panel is visible at runtime, * <CODE>false</CODE> if it is not. * */ public boolean isControlPanelVisible() { return panelVisible; } /** * * Sets the control panel visibility property for this <CODE>MediaPlayer</CODE>. * This property indicates whether or not the control panel is displayed at runtime. * * @param isVisible A boolean value that indicates whether or not the control panel * should be displayed. Set to <CODE>true</CODE> to display the control panel. * */ public void setControlPanelVisible(boolean isVisible) { if (panelVisible != isVisible) { boolean old=panelVisible; if (controlComponent != null) { if (isVisible) { panel.add("South", controlComponent); } else { panel.remove(controlComponent); } } invalidate(); validate(); panelVisible = isVisible; changes.firePropertyChange("controlPanelVisible", new Boolean(old), new Boolean(panelVisible)); } } /** * * Gets the caching control visibility property for this <CODE>MediaPlayer</CODE>. * This property indicates whether or not the caching control is displayed at runtime. * The caching control displays the download progress for media accessed over the network. * * @return <CODE>true</CODE> if the control panel is displayed at runtime, * <CODE>false</CODE> if it is not. * */ public boolean isCachingControlVisible() { return cachingVisible; } /** * * Sets the caching control visibility property for this <CODE>MediaPlayer</CODE>. * This property indicates whether or not the caching control is displayed at runtime. * The caching control displays the download progress for media accessed over the network. * * @param isVisible A boolean value that indicates whether or not the caching control * should be displayed at * runtime. Set to <CODE>true</CODE> to display the control. * */ public void setCachingControlVisible(boolean isVisible) { if (cachingVisible != isVisible) { boolean old = cachingVisible; if (cachingComponent != null) { if (isVisible) { panel.add("South", cachingComponent); } else { panel.remove(cachingComponent); } } invalidate(); validate(); changes.firePropertyChange("cachingControlVisible", new Boolean(old), new Boolean(cachingVisible)); } cachingVisible = isVisible; } /** * * Gets the fixed aspect ratio property for this <CODE>MediaPlayer</CODE>. This * property indicates whether or not the aspect ratio of the video * is maintained when the visual component is resized. * * @return A boolean value that indicates whether or not the aspect ratio is maintained. * Returns <CODE>true</CODE> if it is, <CODE>false</CODE> if it is not. * */ public boolean isFixedAspectRatio() { return fixedAspectRatio; } /** * * Sets the fixed aspect ratio property for this <CODE>MediaPlayer</CODE>. This * property indicates whether or not the aspect ratio of the video * is maintained when the visual component is resized. * * @param isFixed A boolean value that indicates whether or not the aspect * ratio should be maintained. * Set to <CODE>true</CODE> to maintain the aspect ratio. * */ public void setFixedAspectRatio(boolean isFixed) { boolean old = fixedAspectRatio; fixedAspectRatio = isFixed; changes.firePropertyChange("fixedAspectRatio", new Boolean(old), new Boolean(fixedAspectRatio)); } /** * * Specifies whether or not the Zoom Popup Menu is active. * If <CODE>setPopupActive</CODE> is set to false, the popup menu won't be created. * * @param isActive A boolean value that indicates whether or not the popup menu * should be created. * Set to <CODE>true</CODE> to activate the popup menu. * */ public void setPopupActive(boolean isActive) { if (isActive !=isPopupActive) { isPopupActive = isActive; setPopupActive(); } } /** * * Private class activate popup according to private variable isPopupActive. * */ private void setPopupActive() { if (isPopupActive ==true) visualComponent.addMouseListener( mouseListen= new visualMouseAdapter()); else if(mouseListen!=null) visualComponent.removeMouseListener( mouseListen); } // Player methods // method to get the Player's visual component. public Component getVisualComponent() { if (player != null) { return player.getVisualComponent(); } return null; } // method to get the player's gain control, if there is one. public GainControl getGainControl() { if (player != null) { return player.getGainControl(); } return null; } // method to get the player's default control Component. public Component getControlPanelComponent() { if (player != null) { return player.getControlPanelComponent(); } return null; } /** * * Starts the <CODE>MediaPlayer</CODE> as soon as possible. If the <CODE>MediaPlayer</CODE> does * not already have a <CODE>Player</CODE>, * it creates one and then * starts it. * */ public void start() { if (player != null) { player.start(); } else { if (mrl ==null) { initSetCodeBase(); mrl=getMediaLocator(urlString); } if (mrl !=null) { try { player = javax.media.Manager.createPlayer(mrl); player.addControllerListener(selfListener = new InternalControllerAdapter(this)); start(); //add original list to new player if (controlListeners.size()>0) { for (int i=0;i<controlListeners.size();i++) player.addControllerListener( (ControllerListener)controlListeners.elementAt(i)); } } catch (Exception e) { player= null; urlString = " "; Fatal(MediaPlayerResource.getString("UNABLE_CREATE_PLAYER")+e); return; } } else Fatal(MediaPlayerResource.getString("COULD_NOT_START_PLAYER")); } } public void addController(Controller n) { try { if (player != null) { player.addController(n); } } catch (IncompatibleTimeBaseException e) { Fatal(MediaPlayerResource.getString("PLAYER_NO_COMPATIBLE_TIME_BASE")); return; } } /** * * Gets the current <CODE>Player</CODE> for this <CODE>MediaPlayer</CODE>. * * @return The <CODE>Player</CODE> that this <CODE>MediaPlayer</CODE> is currently using. * */ public Player getPlayer() { return player; } public void removeController(Controller old) { if (player != null) { player.removeController(old); } } // MediaHandler method // method to set the source used to obtain content. public void setSource(DataSource data) { try { if (player != null) { player.setSource(data); } } catch (IOException e) { Fatal(MediaPlayerResource.getString("IO_EXCEPTION")+e); return; } catch (IncompatibleSourceException e) { Fatal(MediaPlayerResource.getString("INCOMPATIBLE_SOURCE_EXCEPTION") + e); return; } } // Controller methods // method to get the current state of the player public int getState() { if (player != null) { return player.getState(); } else { return Controller.Unrealized; } } // method to get the target state of the player public int getTargetState() { if (player != null) { return player.getTargetState(); } else { return Controller.Unrealized; } } // method to realize the player public void realize() { if (player != null) { player.realize(); } else { return; } } // method to prefetch the player public void prefetch() { if (player != null) { player.prefetch(); } else { return; } } // method to Abort the current operation and cease any activity // that consumes system resources. public void deallocate() { if (player != null) { debug("in deallocate"); player.deallocate(); } else { return; } } // method to release all resources and cease all activity. public void close() { if (player != null) { panel.removeAll(); player.close(); player = null; } else { return; } } // method to get the Controller's start latency in nanoseconds. public Time getStartLatency() { if (player != null) { return player.getStartLatency(); } else { return LATENCY_UNKNOWN; } } // method to get a list of the Control objects that this Controller supports. public Control[] getControls() { if (player != null) { return player.getControls(); } else { return new Control[0]; } } // method to get the Control that supports the specified class or interface. public Control getControl(String forName) { if (player != null) { return player.getControl(forName); } else { return null; } } // method to specify a ControllerListener to which this Controller will send // events. A Controller can have multiple ControllerListeners. public void addControllerListener(ControllerListener listener) { if (player != null) { player.addControllerListener(listener); } if (!controlListeners.contains(listener)) controlListeners.addElement(listener); } // method to remove the specified listener from this Controller's listener list. public void removeControllerListener(ControllerListener listener) { if (player != null) { player.removeControllerListener(listener); } if (controlListeners.contains(listener)) { controlListeners.removeElement(listener); } } // Clock methods // method to set the TimeBase for this Clock. public void setTimeBase(TimeBase master) { try { if (player != null) { player.setTimeBase(master); } } catch (IncompatibleTimeBaseException e) { Fatal(MediaPlayerResource.getString("INCOMPATIBLE_TIME_BASE")+e); return; } } // method to synchronize the current media time to the specified time-base time // and start the Clock. public void syncStart(Time at) { debug("syncStart "); if (player != null) { player.syncStart(at); } } // method to stop the Clock. public void stop() { if (player != null) { player.stop(); } } /** * Stops the clock and deallocates the system resources used by this * player. * */ public void stopAndDeallocate() { if (player != null) { player.stop(); } } // method to set the media time at which you want the Clock to stop. public void setStopTime(Time stopTime) { if (player != null) { player.setStopTime(stopTime); } } // method to get the last value successfully set by setStopTime. public Time getStopTime() { if (player != null) { return player.getStopTime(); } else { return null; } } // method to set the Clock's media time. public void setMediaTime(Time now) { if (player != null) { player.setMediaTime(now); } } // method to get this Clock's current media time. public Time getMediaTime() { if (player != null) { return player.getMediaTime(); } else { return LATENCY_UNKNOWN; } } /** * Gets the current media time in nanoseconds. * * @return The current media time in nanoseconds. * */ public long getMediaNanoseconds() { if (player != null) { return player.getMediaNanoseconds(); } else { return Long.MAX_VALUE; } } // method to get the current media time or the time until this Clock // will synchronize to its TimeBase. public Time getSyncTime() { if (player != null) { return player.getSyncTime(); } else { return LATENCY_UNKNOWN; } } // method to get the TimeBase that this Clock is using. public TimeBase getTimeBase() { if (player != null) { return player.getTimeBase(); } else { return null; } } // method to get the TimeBase time that corresponds to the specified media time. public Time mapToTimeBase(Time t) { try { if (player != null) { return player.mapToTimeBase(t); } } catch (ClockStoppedException e) { log(MediaPlayerResource.getString("CALL_A_STOPPED_CLOCK")); } return LATENCY_UNKNOWN; } // method to get the current temporal scale factor. public float getRate() { if (player != null) { return player.getRate(); } else { return 0.0f; } } // method to set the temporal scale factor. public float setRate(float factor) { if (player != null) { return player.setRate(factor); } else { return 0.0f; } } // Duration method // method to get the duration of the media represented by this object. public Time getDuration() { if (player != null) { return player.getDuration(); } else { return DURATION_UNKNOWN; } } /** * Ensures the ability to synchronously * change state. Supports serialization. * @param s The state to wait for. The state constants are defined in <CODE>Controller</CODE>. * @see Controller#Unrealized * @see Controller#Realizing * @see Controller#Unrealized * @see Controller#Realized * @see Controller#Prefetching * @see Controller#Prefetched * @see Controller#Started */ public synchronized void waitForState(int s) { while (state != s) { try { wait(1000); } catch (Exception e) {} } } // really simplistic error handling Method errMeth = null; private void Fatal(String name) { // Use reflection to get at the Log. try { if (errMeth == null) { Class cls = Class.forName("com.sun.media.Log"); Class params[] = new Class [] { Class.forName("java.lang.Object") }; errMeth = cls.getMethod("error", params); } Object args[] = new Object [] { name }; errMeth.invoke(null, args); } catch (Throwable t) { System.err.println(name); } } private void log(String name) { // Use reflection to get at the Log. try { if (errMeth == null) { Class cls = Class.forName("com.sun.media.Log"); Class params[] = new Class [] { Class.forName("java.lang.Object") }; errMeth = cls.getMethod("comment", params); } Object args[] = new Object [] { name }; errMeth.invoke(null, args); } catch (Throwable t) { System.err.println(name); } } // Externalizable methods /** * Restores the contents of this object * * @param in The stream that can read primitive and object * data types. * * @exception IOException If an IO error occurs while try to read the object. * @exception java.lang.ClassNotFoundException If no definition for the class can be found. */ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { //save the component state setBounds((Rectangle)in.readObject()); setBackground((Color) in.readObject()); setForeground((Color) in.readObject()); setFont((Font) in.readObject()); setVisible(in.readBoolean()); setEnabled(in.readBoolean()); //restore MediaPlayer state String n = (String)(in.readObject()); if (n != null) { mrl = new MediaLocator(n); } if (mrl !=null) { try { setMediaLocator(mrl); } catch (Exception e) { } } setMediaLocationVisible(in.readBoolean()); panelVisible = in.readBoolean(); cachingVisible = in.readBoolean(); fixedAspectRatio = in.readBoolean(); preferredHeight = in.readInt(); preferredWidth = in.readInt(); //restore Player state if appropriate if (in.readBoolean()) { int s = in.readInt(); int ts = in.readInt(); state = Unrealized; if (s >= Realized) { long mt = in.readLong(); long st = in.readLong(); float r = in.readFloat(); if (ts >= Prefetched) { player.prefetch(); waitForState(Prefetched); } else if (ts >= Realized) { player.realize(); waitForState(Realized); } player.setMediaTime(new Time(mt)); player.setStopTime(new Time(st)); player.setRate(r); float l = in.readFloat(); if (l != -1.0F) { GainControl g = player.getGainControl(); if (g != null) { boolean mute = in.readBoolean(); g.setLevel(l); g.setMute(mute); } else { in.readBoolean(); } } if (ts >= Started) { player.start(); } } } invalidate(); validate(); } /** * * Saves the contents of this object by calling the <CODE>ObjectOutput</CODE> * <CODE>writeObject</CODE> method. * * @param out The stream that can read primitive and object * data types. * @exception IOException If an IO error occurs while attempting to save the object. */ public void writeExternal(ObjectOutput out) throws IOException { //save the component state out.writeObject(getBounds()); out.writeObject(getBackground()); out.writeObject(getForeground()); out.writeObject(getFont()); out.writeBoolean(isVisible()); out.writeBoolean(isEnabled()); //save the MediaPlayer state if (mrl !=null) { out.writeObject(mrl.toExternalForm()); } else { out.writeObject(null); } out.writeBoolean(displayURL); out.writeBoolean(panelVisible); out.writeBoolean(cachingVisible); out.writeBoolean(fixedAspectRatio); out.writeInt(preferredHeight); out.writeInt(preferredWidth); //save the Player state if appropriate if (player == null) { out.writeBoolean(false); } else { out.writeBoolean(true); out.writeInt(player.getState()); out.writeInt(player.getTargetState()); if (player.getState() >= Realized) { out.writeLong(player.getMediaNanoseconds()); out.writeLong(player.getStopTime().getNanoseconds()); out.writeFloat(player.getRate()); //we need to save Gain information: GainControl g; if ((g = player.getGainControl()) != null) { out.writeFloat(g.getLevel()); out.writeBoolean(g.getMute()); } else { out.writeFloat(-1.0F); } } } } /** * * zoomTo(): * method to handle the resize of the visual component of a player * according to its input scale. * * @param float z: the scale for resizing. * */ private void zoomTo(float z) { debug("zoomTo "+z); int ddwidth=0; int ddheight=0; if ((visualComponent != null) && fitVideo) { try { Dimension d=visualComponent.getPreferredSize(); ddwidth = (int)(d.width * z); ddheight = (int)(d.height * z); int dheight=0; if ((controlComponent != null) && isControlPanelVisible()) dheight = controlComponent.getPreferredSize().height; if (displayURL ==true) dheight += urlName.getPreferredSize().height; if (newPanel!=null) newPanel.setSize(ddwidth,dheight); panel.setSize(ddwidth , ddheight+dheight ); if ((fixedAspectRatio ==true) || ((fixedAspectRatio==false)&&(fixtedFirstTime==false))) center(this,panel,true,dheight); else center(this,panel,false,dheight); panel.validate(); } catch (Exception e) { log(MediaPlayerResource.getString("UNABLE_TO_ZOOM")+e); } } } /** * * aspectRatio(): * calculate the aspect Ratio according to the width, height and control * component, MediaLocation text height if they exist * * @param float width: width of panel. * float height: height of panel. * int controllerHeight: including height of control component * and mediaLocation height * */ private float aspectRatio(float width, float height, int controllerHeight) { return (width/((float) (height-controllerHeight))); } /** * * center(): * This method moves the component to the center of parent * container. If fixAspectRatio is specified, then the width * and height will be adjusted accordingly. * * @param parent parent container * comp component to be added to parent * fit if maintain Aspect Ratio * dheight height of controlComponent */ private void center(Container parent, Panel comp, boolean fit, int dheight) { int pwidth = parent.getSize().width; int pheight = parent.getSize().height; int width = comp.getSize().width; int height = comp.getSize().height; if (fit) { float aspect = aspectRatio((float) width,(float) height, dheight); if (width > pwidth) { height = (int) ((float)pwidth/aspect) + dheight; if (height > pheight) { width = (int) (aspect*(pheight-dheight)); height = pheight; } else width = pwidth; comp.setBounds(parent.getBounds().x,parent.getBounds().y,width,height); } else if (height > pheight) { width = (int) (aspect*(pheight-dheight)); height = pheight; comp.setBounds(parent.getBounds().x,parent.getBounds().y,width,height); } } comp.setLocation((pwidth/2)-(width/2), (pheight/2)-(height/2)); comp.setSize( width,height); } /** * * addPopupMenu(): * popup menu for some preset scales of the visualComponent * * @param Component visual: the visual component to add the popup menu * to. * */ private void addPopupMenu(Component visual) { MenuItem mi; ActionListener zoomSelect; zoomMenu = new PopupMenu("Zoom"); zoomSelect = new popupActionListener(); visual.add(zoomMenu); mi = new MenuItem("Scale 1:2"); zoomMenu.add(mi); mi.addActionListener(zoomSelect); mi = new MenuItem("Scale 1:1"); zoomMenu.add(mi); mi.addActionListener(zoomSelect); mi = new MenuItem("Scale 2:1"); zoomMenu.add(mi); mi.addActionListener(zoomSelect); mi = new MenuItem("Scale 4:1"); zoomMenu.add(mi); mi.addActionListener(zoomSelect); } /** * Resizes the visual <CODE>Component</CODE>, control <CODE>Component</CODE>, * and <CODE>urlName</CODE> according to the specified dimensions. * * * @param x The x coordinate of the rectangle. * @param y The y coordinate of the rectangle. * @param w The width of the rectangle. * @param h The height of the rectangle. * */ public void setBounds(int x, int y, int w, int h) { debug("setBounds "+x +" "+y+" "+w+" "+h+" "); super.setBounds(x,y,w,h); Dimension d = getSize(); int pheight = d.height; int pwidth = d.width; int p = 0; int totalHeight = 0; if ((urlName!=null) &&(isMediaLocationVisible())) { totalHeight = urlFieldHeight=urlName.getPreferredSize().height; if ((pheight < 5) && (displayURL==true)) { pheight = 5; } } if ((controlComponent != null) && isControlPanelVisible()) { controlPanelHeight=controlComponent.getPreferredSize().height; totalHeight +=controlPanelHeight; if (d.width < 160) d.width = 160; if ((pheight < 2) && (visualComponent != null)) { pheight += 2; } } if (visualComponent !=null) { Dimension vSize = visualComponent.getPreferredSize(); if (fixedAspectRatio == true) { //compare the ratio of parent and panel, and get the smaller number if (((float)pwidth/(float)vSize.width) >= ((float)(pheight-totalHeight)/ (float)(vSize.height-totalHeight))) curZoomValue = ((float)(pheight-totalHeight)/ (float)(vSize.height-totalHeight)); else curZoomValue = (float)pwidth/(float)vSize.width; if (curZoomValue <1.0) curZoomValue=1; zoomTo(curZoomValue); } else panel.setBounds(getBounds()); } else { panel.setSize(getSize()); validate(); } } /** * * Gets the dimensions of the preferred size. * * @return A <CODE>Dimension</CODE> that represents the preferred size. * */ public Dimension getPreferredSize() { return new Dimension(preferredWidth, preferredHeight); } /** * * Adds a <CODE>PropertyChangeListener</CODE> to the listener list. * * @param c The <CODE>PropertyChangeListener</CODE> to be * added. * */ public void addPropertyChangeListener(PropertyChangeListener c) { changes.addPropertyChangeListener(c); } /** * * Removes a <CODE>PropertyChangeListener</CODE> from the listener list. * * @param c The <CODE>PropertyChangeListener</CODE> to be * removed. * */ public void removePropertyChangeListener(PropertyChangeListener c) { changes.removePropertyChangeListener(c); } /** * Sets the codebase of the running applet. * * @param cb The <CODE>URL</CODE> for the codebase of the currently running applet. * */ public void setCodeBase(URL cb) { mpCodeBase = cb; } /** * An inner class that's a component listener for receiving component events. */ private class visualComponentAdapter extends ComponentAdapter { private MediaPlayer thisBean; /** * Constructor. * * @param b The instance of a <CODE>MediaPlayer</CODE> bean. * */ public visualComponentAdapter(MediaPlayer b) { super(); thisBean = b; } /** * Gets the notification that the bean has been resized and centers the panel inside the bean. * * @param ce The <CODE>Component</CODE> event. * */ public void componentResized(ComponentEvent ce) { if (ce.getSource() == thisBean) { debug("componentResized"); int dheight=0; if ((controlComponent != null) && isControlPanelVisible()) dheight =controlComponent.getPreferredSize().height; center(thisBean,panel,isFixedAspectRatio(),dheight); } } } /** * An internal class for receiving mouse events. Only need to implement * the methods we are interested in. * */ private class visualMouseAdapter extends MouseAdapter { /** * * Displays the zoomMenu according to the x, y values from the input <CODE>MouseEvent</CODE>. * * @param me: The <CODE>MouseEvent</CODE> that contains the mouse action information. * */ public void mousePressed(MouseEvent me) { if (me.isPopupTrigger()) { zoomMenu.show(visualComponent, me.getX(), me.getY()); } } /** * * Displays the zoomMenu according the to x, y values from the input <CODE>MouseEvent</CODE>. * * @param me The <CODE>MouseEvent</CODE> that contains the mouse action information. * */ public void mouseReleased(MouseEvent me) { if (me.isPopupTrigger()) { zoomMenu.show(visualComponent, me.getX(), me.getY()); } } /** * * Displays the zoomMenu according to the x, y values from the input <CODE>MouseEvent</CODE>. * * @param me The <CODE>MouseEvent</CODE> that contains the mouse action information. * */ public void mouseClicked(MouseEvent me) { if (me.isPopupTrigger()) { zoomMenu.show(visualComponent, me.getX(), me.getY()); } } } /** * * An <CODE>ActionListener</CODE> for zoom panel selection. * */ private class popupActionListener implements ActionListener { /** * Calls setZoomTo to resize the visual * component according to the option the user was chosen. * * @param ae Contains the information about * the selection of the zoomMenu. * */ public void actionPerformed(ActionEvent ae) { String action = ae.getActionCommand(); setZoomTo(action); } } /** * Saves the media stop time to a variable. * */ public void saveMediaTime() { mediaTime = getMediaTime(); } /** * Restores the media time saved by <CODE>saveMediaTime</CODE> * so that the video resumes from the time it was stoped. * */ public void restoreMediaTime() { setMediaTime(mediaTime); } //{{DECLARE_CONTROLS //}} private void debug(String s) { // System.out.println(s); } }