+++ /dev/null
-package tim.prune.function.autoplay;
-
-import java.awt.Component;
-import java.awt.FlowLayout;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import java.util.Iterator;
-import java.util.TreeSet;
-
-import javax.swing.BoxLayout;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JDialog;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-
-import tim.prune.App;
-import tim.prune.GenericFunction;
-import tim.prune.I18nManager;
-import tim.prune.data.Field;
-import tim.prune.data.Timestamp;
-import tim.prune.data.Track;
-import tim.prune.gui.GuiGridLayout;
-import tim.prune.gui.IconManager;
-import tim.prune.gui.WholeNumberField;
-
-/**
- * Function to handle the autoplay of a track
- */
-public class AutoplayFunction extends GenericFunction implements Runnable
-{
- /** Dialog */
- private JDialog _dialog = null;
- /** Entry field for number of seconds to autoplay for */
- private WholeNumberField _durationField = null;
- /** Checkbox for using point timestamps */
- private JCheckBox _useTimestampsCheckbox = null;
- /** Buttons for controlling autoplay */
- private JButton _rewindButton = null, _pauseButton = null, _playButton = null;
- /** Flag for recalculating all the times */
- private boolean _needToRecalculate = true;
- /** Point list */
- private PointList _pointList = null;
- /** Flag to see if we're still running or not */
- private boolean _running = false;
- /** Remember the time we started playing */
- private long _startTime = 0L;
-
-
- /**
- * Constructor
- * @param inApp App object
- */
- public AutoplayFunction(App inApp) {
- super(inApp);
- }
-
- @Override
- public String getNameKey() {
- return "function.autoplay";
- }
-
- /**
- * Begin the function
- */
- public void begin()
- {
- if (_dialog == null)
- {
- _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), true);
- _dialog.setLocationRelativeTo(_parentFrame);
- _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
- _dialog.getContentPane().add(makeDialogComponents());
- _dialog.pack();
- _dialog.setResizable(false);
- _dialog.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- _running = false;
- super.windowClosing(e);
- }
- });
- }
- // Don't select any point
- _app.getTrackInfo().selectPoint(-1);
- // enable buttons
- enableButtons(false, true); // can't pause, can play
- // MAYBE: reset duration if it's too long
- // Disable point checkbox if there aren't any times
- final boolean hasTimes = _app.getTrackInfo().getTrack().hasData(Field.TIMESTAMP);
- _useTimestampsCheckbox.setEnabled(hasTimes);
- if (!hasTimes)
- {
- _useTimestampsCheckbox.setSelected(false);
- }
-
- _needToRecalculate = true;
- _dialog.setVisible(true);
- }
-
-
- /**
- * Create dialog components
- * @return Panel containing all gui elements in dialog
- */
- private Component makeDialogComponents()
- {
- JPanel dialogPanel = new JPanel();
- dialogPanel.setLayout(new BoxLayout(dialogPanel, BoxLayout.Y_AXIS));
- // Duration panel
- JPanel durationPanel = new JPanel();
- GuiGridLayout grid = new GuiGridLayout(durationPanel);
- grid.add(new JLabel(I18nManager.getText("dialog.autoplay.duration") + " :"));
- _durationField = new WholeNumberField(3);
- _durationField.setValue(60); // default is one minute
- _durationField.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- onParamsChanged();
- }
- });
- grid.add(_durationField);
- durationPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
- dialogPanel.add(durationPanel);
- // Checkbox
- _useTimestampsCheckbox = new JCheckBox(I18nManager.getText("dialog.autoplay.usetimestamps"));
- _useTimestampsCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT);
- dialogPanel.add(_useTimestampsCheckbox);
- _useTimestampsCheckbox.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- onParamsChanged();
- }
- });
- // Button panel
- JPanel buttonPanel = new JPanel();
- buttonPanel.setLayout(new FlowLayout(FlowLayout.CENTER));
- buttonPanel.add(_rewindButton = new JButton(IconManager.getImageIcon(IconManager.AUTOPLAY_REWIND)));
- _rewindButton.setToolTipText(I18nManager.getText("dialog.autoplay.rewind"));
- _rewindButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent arg0) {
- onRewindPressed();
- }
- });
- buttonPanel.add(_pauseButton = new JButton(IconManager.getImageIcon(IconManager.AUTOPLAY_PAUSE)));
- _pauseButton.setToolTipText(I18nManager.getText("dialog.autoplay.pause"));
- _pauseButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent arg0) {
- onPausePressed();
- }
- });
- buttonPanel.add(_playButton = new JButton(IconManager.getImageIcon(IconManager.AUTOPLAY_PLAY)));
- _playButton.setToolTipText(I18nManager.getText("dialog.autoplay.play"));
- _playButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent arg0) {
- onPlayPressed();
- }
- });
- buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
- dialogPanel.add(buttonPanel);
- return dialogPanel;
- }
-
- /**
- * React to a change to either the duration or the checkbox
- */
- private void onParamsChanged()
- {
- onRewindPressed();
- enableButtons(false, _durationField.getValue() > 0);
- _needToRecalculate = true;
- }
-
- /**
- * React to rewind button pressed - stop and go back to the first point
- */
- private void onRewindPressed()
- {
- //System.out.println("Rewind! Stop thread if playing");
- _running = false;
- if (_pointList != null)
- {
- _pointList.set(0);
- _app.getTrackInfo().selectPoint(_pointList.getCurrentPointIndex());
- }
- }
-
- /**
- * React to pause button pressed - stop scrolling but maintain position
- */
- private void onPausePressed()
- {
- //System.out.println("Pause! Stop thread if playing");
- _running = false;
- enableButtons(false, true);
- }
-
- /**
- * React to play button being pressed - either start or resume
- */
- private void onPlayPressed()
- {
- //System.out.println("Play!");
- if (_needToRecalculate) {
- recalculateTimes();
- }
- enableButtons(true, false);
- if (_pointList.isAtStart() || _pointList.isFinished())
- {
- _pointList.set(0);
- _startTime = System.currentTimeMillis();
- }
- else
- {
- // Get current millis from pointList, reset _startTime
- _startTime = System.currentTimeMillis() - _pointList.getCurrentMilliseconds();
- }
- new Thread(this).start();
- }
-
- /**
- * Recalculate the times using the dialog settings
- */
- private void recalculateTimes()
- {
- //System.out.println("Recalculate using params " + _durationField.getValue()
- // + " and " + (_useTimestampsCheckbox.isSelected() ? "times" : "indexes"));
- if (_useTimestampsCheckbox.isSelected()) {
- _pointList = generatePointListUsingTimes(_app.getTrackInfo().getTrack(), _durationField.getValue());
- }
- else {
- _pointList = generatePointListUsingIndexes(_app.getTrackInfo().getTrack().getNumPoints(), _durationField.getValue());
- }
- _needToRecalculate = false;
- }
-
- /**
- * Enable and disable the pause and play buttons
- * @param inCanPause true to enable pause button
- * @param inCanPlay true to enable play button
- */
- private void enableButtons(boolean inCanPause, boolean inCanPlay)
- {
- _pauseButton.setEnabled(inCanPause);
- _playButton.setEnabled(inCanPlay);
- }
-
- /**
- * Generate a points list based just on the point timestamps
- * (points without timestamps will be ignored)
- * @param inTrack track object
- * @param inDuration number of seconds to play
- * @return PointList object
- */
- private static PointList generatePointListUsingTimes(Track inTrack, int inDuration)
- {
- // Make a Set of all the points with timestamps and sort them
- TreeSet<PointInfo> set = new TreeSet<PointInfo>();
- int numPoints = inTrack.getNumPoints();
- for (int i=0; i<numPoints; i++)
- {
- PointInfo info = new PointInfo(inTrack.getPoint(i), i);
- if (info.getTimestamp() != null) {
- set.add(info);
- }
- }
- // For each point, keep track of the time since the previous time
- Timestamp previousTime = null;
- long trackMillis = 0L;
- // Copy info to point list
- numPoints = set.size();
- PointList list = new PointList(numPoints);
- Iterator<PointInfo> it = set.iterator();
- while (it.hasNext())
- {
- PointInfo info = it.next();
- if (previousTime != null)
- {
- if (info.getSegmentFlag()) {
- trackMillis += 1000; // just add a second if it's a new segment
- }
- else {
- trackMillis += (info.getTimestamp().getMillisecondsSince(previousTime));
- }
- }
- previousTime = info.getTimestamp();
- list.setPoint(trackMillis, info.getIndex());
- }
- // Now normalize the list to the requested length
- list.normalize(inDuration);
- return list;
- }
-
-
- /**
- * Generate a points list based just on indexes, ignoring timestamps
- * @param inNumPoints number of points in track
- * @param inDuration number of seconds to play
- * @return PointList object
- */
- private static PointList generatePointListUsingIndexes(int inNumPoints, int inDuration)
- {
- // simple case, just take all the points in the track
- PointList list = new PointList(inNumPoints);
- // Add each of the points in turn
- for (int i=0; i<inNumPoints; i++)
- {
- list.setPoint(i, i);
- }
- list.normalize(inDuration);
- return list;
- }
-
- /**
- * Run method, for scrolling in separate thread
- */
- public void run()
- {
- _running = true;
- _app.getTrackInfo().selectPoint(_pointList.getCurrentPointIndex());
- while (_running && !_pointList.isFinished())
- {
- _pointList.set(System.currentTimeMillis() - _startTime);
- final int pointIndex = _pointList.getCurrentPointIndex();
- //System.out.println("Set point index to " + pointIndex);
- _app.getTrackInfo().selectPoint(pointIndex);
- long waitInterval = _pointList.getMillisUntilNextPoint(System.currentTimeMillis() - _startTime);
- if (waitInterval < 20) {waitInterval = 20;}
- try {Thread.sleep(waitInterval);}
- catch (InterruptedException ie) {}
- }
- _running = false;
- enableButtons(false, true);
- }
-}