/* * @(#)ProgressSlider.java 1.37 02/08/21 * * Copyright (c) 1996-2002 Sun Microsystems, Inc. All rights reserved. */ package com.sun.media.ui; import java.security.*; import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.awt.*; import java.awt.event.*; import javax.media.*; import com.sun.media.controls.*; import com.sun.media.util.*; import com.sun.media.JMFSecurity; import com.sun.media.JMFSecurityManager; import com.ms.security.PermissionID; import com.ms.security.PolicyEngine; public class ProgressSlider extends BasicComp implements MouseListener, MouseMotionListener, Runnable, ComponentListener, ControllerListener { Image imageGrabber; Image imageGrabberDown; int grabberWidth; int grabberHeight; boolean grabbed; boolean entered; int grabberPosition; int leftBorder = 0; int rightBorder = 0; int sliderWidth; MediaThread timer = null; protected boolean justSeeked = false; protected boolean stopTimer = false; private static JMFSecurity jmfSecurity = null; private static boolean securityPrivelege=false; private Method m[] = new Method[1]; private Class cl[] = new Class[1]; private Object args[][] = new Object[1][0]; private Player player; private DefaultControlPanel controlPanel; private ToolTip toolTip = null; private double progressCaching = 1.0; // 0.0 - 1.0 private boolean resetMediaTime = false; static { try { jmfSecurity = JMFSecurityManager.getJMFSecurity(); securityPrivelege = true; } catch (SecurityException e) { } } public ProgressSlider(String label, DefaultControlPanel cp, Player p) { super(label); player = p; controlPanel = cp; // Load the images imageGrabber = fetchImage("grabber.gif"); imageGrabberDown = fetchImage("grabber-pressed.gif"); // Get the sizes of the images grabberWidth = imageGrabber.getWidth(this); grabberHeight = imageGrabber.getHeight(this); leftBorder = grabberWidth / 2; rightBorder = leftBorder; addMouseListener( this ); addMouseMotionListener( this ); grabberPosition = 0; grabbed = false; entered = false; this.height = 18; this.width = 20; sliderWidth = this.width - leftBorder - rightBorder; this.addComponentListener ( this ); player.addControllerListener ( this ); } public void addNotify() { super.addNotify(); if ( /*securityPrivelege && */ (jmfSecurity != null) ) { String permission = null; try { if (jmfSecurity.getName().startsWith("jmf-security")) { permission = "thread"; jmfSecurity.requestPermission(m, cl, args, JMFSecurity.THREAD); m[0].invoke(cl[0], args[0]); permission = "thread group"; jmfSecurity.requestPermission(m, cl, args, JMFSecurity.THREAD_GROUP); m[0].invoke(cl[0], args[0]); } else if (jmfSecurity.getName().startsWith("internet")) { PolicyEngine.checkPermission(PermissionID.THREAD); PolicyEngine.assertPermission(PermissionID.THREAD); } } catch (Throwable e) { if (JMFSecurityManager.DEBUG) { System.err.println("Unable to get " + permission + " privilege " + e); } securityPrivelege = false; // TODO: Do the right thing if permissions cannot be obtained. // User should be notified via an event } } if ( (jmfSecurity != null) && (jmfSecurity.getName().startsWith("jdk12"))) { try { final ProgressSlider slider = this; Constructor cons = jdk12CreateThreadRunnableAction.cons; timer = (MediaThread) jdk12.doPrivM.invoke( jdk12.ac, new Object[] { cons.newInstance( new Object[] { MediaThread.class, this })}); timer.setName("Progress Slider thread"); // timer.useControlPriority(); cons = jdk12PriorityAction.cons; jdk12.doPrivM.invoke( jdk12.ac, new Object[] { cons.newInstance( new Object[] { timer, new Integer(timer.getControlPriority()) })}); stopTimer = false; timer.start(); } catch (Exception e) { } } else { timer = new MediaThread(this); timer.setName("Progress Slider thread"); timer.useControlPriority(); stopTimer = false; timer.start(); } } // Cannot make removeNotify synchronized. It will deadlock // with other mouse event listeners. So we'll have to create // another lock to synchronize removeNotify and dispose. Object disposeLock = new Object(); Object syncStop = new Object(); public void removeNotify() { if (timer != null) { synchronized (syncStop) { stopTimer = true; timer = null; } } synchronized (disposeLock) { if ( toolTip != null ) { toolTip.setVisible ( false ); //toolTip = null; } } super.removeNotify(); } public synchronized void dispose() { synchronized (syncStop) { if (timer != null) { stopTimer = true; } } removeMouseListener( this ); removeMouseMotionListener( this ); removeComponentListener ( this ); synchronized (disposeLock) { if (toolTip != null) { toolTip.dispose(); toolTip = null; } } timer = null; player = null; } public void run() { int counter = 0; int pausecnt = -1; int sleepTime; boolean doUpdate = true; while (!stopTimer) { try { if ( player != null && player.getState() == Controller.Started) { doUpdate = true; pausecnt = -1; } else if (player != null && pausecnt < 5) { pausecnt ++; doUpdate = true; } else if ( resetMediaTime ) { doUpdate = true; resetMediaTime = false; } else { doUpdate = false; } try { if (doUpdate) { long nanoDuration = player.getDuration().getNanoseconds(); if (nanoDuration > 0) { long nanoTime = player.getMediaNanoseconds(); // Update the time less often if the slider is not // present. seek((float)nanoTime / nanoDuration); if ( grabbed == false ) updateToolTip ( nanoTime ); } } } catch (Exception e) { } sleepTime = (isEnabled() ? 200 : 1000); try { Thread.sleep(sleepTime); } catch (Exception e) {} counter++; if (counter == 1000/sleepTime) { counter = 0; controlPanel.update(); } if (justSeeked) { justSeeked = false; try { Thread.sleep(1000); } catch (Exception e) {} } } catch (Exception e) { } } } public void paint(Graphics g) { // Draw the rod int x; int y; int grabberY; int downloadCredit; String strTime; Font font; FontMetrics fontMetrics; if (isEnabled()) { y = (this.height / 2) - 2; grabberY = (this.height / 2) - (grabberHeight / 2); g.setColor( getBackground().darker() ); g.drawRect (leftBorder, y, sliderWidth, 3); g.setColor(getBackground()); downloadCredit = grabberWidth; g.draw3DRect(leftBorder, y, (int)((sliderWidth - downloadCredit) * progressCaching + downloadCredit), 3, false); // Paint the download display /* if ((displayControl != null) && displayControl.isEnable()) { int percent = (int) displayControl.getMaxValue(); if (percent < 100) { g.setColor(Color.yellow); // Loading zone x = sliderWidth * percent / 100 + 3; y += 2; g.drawLine(x, y, this.width - 4, y); g.setColor(Color.green); g.drawLine(0, y, x, y); } else { g.setColor(Color.green); y += 2; g.drawLine(0, y, this.width - 4, y); } } */ // Paint the grabber if (grabbed || entered) g.drawImage(imageGrabberDown, grabberPosition + leftBorder - grabberWidth / 2, grabberY, this); else g.drawImage(imageGrabber, grabberPosition + leftBorder - grabberWidth / 2, grabberY, this); } else if (player != null) { strTime = formatTime ( player.getMediaNanoseconds() ); font = this. getFont (); g.setFont ( font ); fontMetrics = this.getFontMetrics ( font ); g.drawString ( strTime, 2, 2 + fontMetrics.getAscent() ); } } private void sliderSeek(float fraction) { if (player == null) return; long value = (long) (fraction * player.getDuration().getNanoseconds()); justSeeked = true; if (value >= 0) { player.setMediaTime(new Time(value)); controlPanel.resetPauseCount(); controlPanel.update(); } } public void seek(float fraction) { if (justSeeked) return; if (!grabbed) { int newPosition = (int) (fraction * sliderWidth); if (newPosition > sliderWidth) newPosition = sliderWidth; if (newPosition < 0) newPosition = 0; if (grabberPosition != newPosition || !isEnabled()) { grabberPosition = newPosition; repaint(); } } } public Dimension getPreferredSize() { return new Dimension(20, this.height); } public float sliderToSeek(int x) { float s = (float)(x) / (float)(sliderWidth); return s; } public int mouseToSlider(int x) { if (x < leftBorder) x = leftBorder; if (x > this.width - rightBorder) x = this.width - rightBorder; x -= leftBorder; return x; } public void mousePressed(MouseEvent me) { if (!isEnabled()) return; grabbed = true; grabberPosition = mouseToSlider(me.getX()); repaint(); } public synchronized void mouseReleased(MouseEvent me) { if (!isEnabled()) return; grabbed = false; grabberPosition = mouseToSlider(me.getX()); float seek = sliderToSeek(grabberPosition); sliderSeek(seek); if ( toolTip != null && entered == false ) { toolTip.dispose (); toolTip = null; } repaint(); } public void mouseClicked(MouseEvent me) { } public synchronized void mouseEntered(MouseEvent me) { // Dimension dim; Point pointScreen; entered = true; if ( toolTip == null && isEnabled() && player != null) { toolTip = new ToolTip ( "time/duration" ); updateToolTip ( player.getMediaNanoseconds() ); if ( this.isShowing() ) { pointScreen = this.getLocationOnScreen (); // dim = toolTip.getSize (); // pointScreen.x += me.getX() - dim.width - 2; // pointScreen.y += me.getY(); // dim = this.getSize (); pointScreen.y += this.height + 4; toolTip.setLocation ( pointScreen ); toolTip.show (); } } repaint(); } public synchronized void mouseExited(MouseEvent me) { if ( toolTip != null && grabbed == false ) { toolTip.dispose (); toolTip = null; } if (!isEnabled()) return; entered = false; repaint(); } public synchronized void mouseMoved(MouseEvent me) { Dimension dim; Point pointScreen; if ( toolTip != null && this.isShowing() ) { dim = toolTip.getSize (); pointScreen = this.getLocationOnScreen (); pointScreen.x += me.getX() - dim.width - 2; pointScreen.y += me.getY(); // toolTip.setLocation ( pointScreen ); } } public synchronized void mouseDragged(MouseEvent me) { float seek; long value; if (!isEnabled() || player == null) return; int newPosition = mouseToSlider(me.getX()); if (newPosition != grabberPosition) { grabberPosition = newPosition; seek = sliderToSeek(grabberPosition); if (player.getState() != Controller.Started) sliderSeek(seek); value = (long) (seek * player.getDuration().getNanoseconds()); updateToolTip ( value ); repaint(); } } public void componentResized ( ComponentEvent event ) { Dimension dim; dim = this.getSize (); if ( dim.width - leftBorder - rightBorder < 1 ) return; grabberPosition = (int) (grabberPosition * ((float)(dim.width-leftBorder-rightBorder) / (this.width - leftBorder - rightBorder))); this.width = dim.width; sliderWidth = this.width - leftBorder - rightBorder; } public void componentMoved ( ComponentEvent event ) { } public void componentShown ( ComponentEvent event ) { } public void componentHidden ( ComponentEvent event ) { } public synchronized void controllerUpdate ( ControllerEvent event ) { CachingControl cachingControl; long length; long progress; if ( event instanceof CachingControlEvent ) { cachingControl = ((CachingControlEvent)event).getCachingControl(); length = cachingControl.getContentLength (); progress = cachingControl.getContentProgress (); progressCaching = (double)progress / length; repaint (); } else if ( event instanceof MediaTimeSetEvent) { resetMediaTime = true; } } private String formatTime ( Time time ) { long nano; String strTime = new String ( "<unknown>" ); if ( time == null || time == Time.TIME_UNKNOWN || time == javax.media.Duration.DURATION_UNKNOWN ) return ( strTime ); nano = time.getNanoseconds(); strTime = formatTime ( nano ); return ( strTime ); } private String formatTime ( long nanoSeconds ) { int hours; int minutes; int seconds; int hours10; int minutes10; int seconds10; long nano10; String strTime; seconds = (int) (nanoSeconds / Time.ONE_SECOND); hours = seconds / 3600; minutes = ( seconds - hours * 3600 ) / 60; seconds = seconds - hours * 3600 - minutes * 60; nanoSeconds = (long) ((nanoSeconds % Time.ONE_SECOND) / (Time.ONE_SECOND/100)); hours10 = hours / 10; hours = hours % 10; minutes10 = minutes / 10; minutes = minutes % 10; seconds10 = seconds / 10; seconds = seconds % 10; nano10 = nanoSeconds / 10; nanoSeconds = nanoSeconds % 10; strTime = new String ( "" + hours10 + hours + ":" + minutes10 + minutes + ":" + seconds10 + seconds + "." + nano10 + nanoSeconds ); return ( strTime ); } public void updateToolTip ( long nanoMedia ) { String strTool; Time timeDuration; if ( toolTip == null || player == null ) return; timeDuration = player.getDuration (); strTool = new String ( formatTime(nanoMedia) + " / " + formatTime(timeDuration) ); toolTip.setText ( strTool ); } }