/* * Open Source Physics software is free software as described near the bottom of this code file. * * For additional information and documentation on Open Source Physics please see: * <http://www.opensourcephysics.org/> */ /* * The org.opensourcephysics.media.core package defines the Open Source Physics * media framework for working with video and other media. * * Copyright (c) 2014 Douglas Brown and Wolfgang Christian. * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA * or view the license online at http://www.gnu.org/copyleft/gpl.html * * For additional information and documentation on Open Source Physics, * please see <http://www.opensourcephysics.org/>. */ package org.opensourcephysics.media.core; import java.beans.PropertyChangeEvent; import javax.swing.SwingUtilities; import org.opensourcephysics.controls.XML; /** * This is a ClipControl that uses the video itself for timing. * * @author Douglas Brown * @version 1.0 */ public class VideoClipControl extends ClipControl { /** * Constructs a VideoClipControl. * * @param videoClip the video clip */ protected VideoClipControl(VideoClip videoClip) { super(videoClip); video.addPropertyChangeListener(this); } /** * Plays the clip. */ public void play() { video.play(); } /** * Stops at the next step. */ public void stop() { video.stop(); } /** * Steps forward one step. */ public void step() { video.stop(); setStepNumber(stepNumber+1); } /** * Steps back one step. */ public void back() { video.stop(); setStepNumber(stepNumber-1); } /** * Sets the step number. * * @param n the desired step number */ public void setStepNumber(int n) { if(n==stepNumber && clip.stepToFrame(n)==getFrameNumber()) { return; } n = Math.max(0, n); final int stepNum = Math.min(clip.getStepCount()-1, n); Runnable runner = new Runnable() { public void run() { int m = clip.stepToFrame(stepNum)+clip.getFrameShift(); video.setFrameNumber(m); } }; SwingUtilities.invokeLater(runner); } /** * Gets the step number. * * @return the current step number */ public int getStepNumber() { return clip.frameToStep(video.getFrameNumber()); } /** * Sets the play rate. * * @param newRate the desired rate */ public void setRate(double newRate) { if((newRate==0)||(newRate==rate)) { return; } rate = Math.abs(newRate); video.setRate(rate); } /** * Gets the play rate. * * @return the current rate */ public double getRate() { return video.getRate(); } /** * Turns on/off looping. * * @param loops <code>true</code> to turn looping on */ public void setLooping(boolean loops) { if(loops==isLooping()) { return; } video.setLooping(loops); } /** * Gets the looping status. * * @return <code>true</code> if looping is on */ public boolean isLooping() { return video.isLooping(); } /** * Gets the current frame number. * * @return the frame number */ public int getFrameNumber() { int n = video.getFrameNumber()-clip.getFrameShift(); n = Math.max(0, n); // can't be negative return n; } /** * Gets the playing status. * * @return <code>true</code> if playing */ public boolean isPlaying() { return video.isPlaying(); } /** * Gets the current time in milliseconds measured from step 0. * * @return the current time */ public double getTime() { int n = video.getFrameNumber(); return(video.getFrameTime(n)-video.getStartTime())*timeStretch; } /** * Gets the start time of the specified step measured from step 0. * * @param stepNumber the step number * @return the step time */ public double getStepTime(int stepNumber) { int n = clip.stepToFrame(stepNumber); return(video.getFrameTime(n)-video.getStartTime())*timeStretch; } /** * Sets the frame duration. * * @param duration the desired frame duration in milliseconds */ public void setFrameDuration(double duration) { if(duration==0) { return; } duration = Math.abs(duration); double ti = video.getFrameTime(video.getStartFrameNumber()); double tf = video.getFrameTime(video.getEndFrameNumber()); int count = video.getEndFrameNumber()-video.getStartFrameNumber(); if(count!=0) { timeStretch = duration*count/(tf-ti); } support.firePropertyChange("frameduration", null, new Double(duration)); //$NON-NLS-1$ } /** * Gets the mean frame duration in milliseconds. * * @return the frame duration in milliseconds */ public double getMeanFrameDuration() { int count = video.getEndFrameNumber()-video.getStartFrameNumber(); if(count!=0) { double ti = video.getFrameTime(video.getStartFrameNumber()); double tf = video.getFrameTime(video.getEndFrameNumber()); return timeStretch*(tf-ti)/count; } return timeStretch*video.getDuration()/video.getFrameCount(); } /** * Responds to property change events. VideoClipControl listens for the * following events: "playing", "looping", "rate" and "framenumber" from Video. * * @param e the property change event */ public void propertyChange(PropertyChangeEvent e) { String name = e.getPropertyName(); if(name.equals("framenumber")) { // from Video //$NON-NLS-1$ int n = ((Integer) e.getNewValue()).intValue(); if(n==videoFrameNumber) { super.setFrameNumber(n-clip.getFrameShift()); return; } super.setFrameNumber(n-clip.getFrameShift()); Integer nInt = new Integer(stepNumber); support.firePropertyChange("stepnumber", null, nInt); // to VideoPlayer //$NON-NLS-1$ } else if(name.equals("playing")) { // from Video //$NON-NLS-1$ // boolean playing = ((Boolean) e.getNewValue()).booleanValue(); // if(!playing) { // setStepNumber(stepNumber+1); // } support.firePropertyChange(e); // to VideoPlayer } else if(name.equals("rate") // from Video //$NON-NLS-1$ || name.equals("looping")) { // from Video //$NON-NLS-1$ support.firePropertyChange(e); // to VideoPlayer } else super.propertyChange(e); } /** * Removes this listener from the video so it can be garbage collected. */ public void dispose() { video.removePropertyChangeListener(this); } /** * Returns an XML.ObjectLoader to save and load data for this class. * * @return the object loader */ public static XML.ObjectLoader getLoader() { return new Loader(); } } /* * Open Source Physics software is free software; you can redistribute * it and/or modify it under the terms of the GNU General Public License (GPL) as * published by the Free Software Foundation; either version 2 of the License, * or(at your option) any later version. * Code that uses any portion of the code in the org.opensourcephysics package * or any subpackage (subdirectory) of this package must must also be be released * under the GNU GPL license. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA * or view the license online at http://www.gnu.org/copyleft/gpl.html * * Copyright (c) 2007 The Open Source Physics project * http://www.opensourcephysics.org */