package tim.prune.function.autoplay; /** * Class to hold a list of points and hold a running position */ public class PointList { /** Array of milliseconds for each point */ private long[] _millis = null; /** Array of indexes of corresponding points */ private int[] _indexes = null; /** Array index of current position */ private int _currentItem = 0; /** Max array index */ private int _maxItem = 0; /** * Constructor * @param inNumPoints number of points */ public PointList(int inNumPoints) { _millis = new long[inNumPoints]; _indexes = new int[inNumPoints]; _currentItem = 0; _maxItem = inNumPoints - 1; } /** * Add a point to the array * @param inMillis milliseconds since start * @param inIndex point index */ public void setPoint(long inMillis, int inIndex) { _millis[_currentItem] = inMillis; _indexes[_currentItem] = inIndex; _currentItem++; } /** * Set the position using the current milliseconds * @param inMillis milliseconds since start */ public void set(long inMillis) { if (isFinished() || inMillis < _millis[_currentItem]) { // must be reset _currentItem = 0; } while (_currentItem < _maxItem && _millis[_currentItem + 1] < inMillis) { _currentItem++; } } /** * Normalize the list to cover the requested number of seconds duration * @param inSeconds length of autoplay sequence in seconds */ public void normalize(int inSeconds) { if (_maxItem <= 0) { return; // nothing to normalize } long currentDuration = _millis[_maxItem] - _millis[0]; if (currentDuration > 0L) { double multFactor = inSeconds * 1000.0 / currentDuration; for (int i=0; i<=_maxItem; i++) { _millis[i] = (long) (_millis[i] * multFactor); } } } /** @return the milliseconds of the current point */ public long getCurrentMilliseconds() { if (isAtStart() || isFinished()) { return 0L; } return _millis[_currentItem]; } /** @return the index of the current point */ public int getCurrentPointIndex() { return _indexes[_currentItem]; } /** @return true if we're on the first point */ public boolean isAtStart() { return _currentItem == 0; } /** @return true if we're on the last point */ public boolean isFinished() { return _currentItem >= _maxItem; } /** * @param inCurrentMillis current time in milliseconds since start * @return number of milliseconds to wait until next point is due */ public long getMillisUntilNextPoint(long inCurrentMillis) { if (isFinished() || _millis[_currentItem+1] < _millis[_currentItem]) { return 0; // no next point } return _millis[_currentItem+1] - inCurrentMillis; } }