/*
* org.openmicroscopy.shoola.agents.imviewer.util.player.MoviePlayer
*
*------------------------------------------------------------------------------
* Copyright (C) 2006-2014 University of Dundee. All rights reserved.
*
*
* This program 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 program 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 program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*------------------------------------------------------------------------------
*/
package org.openmicroscopy.shoola.agents.imviewer.util.player;
//Java imports
import java.awt.event.ActionEvent;
//Third-party libraries
//Application-internal dependencies
import org.openmicroscopy.shoola.agents.imviewer.view.ImViewer;
/**
* Player to play movies across z-sections/timepoints.
*
* @author Jean-Marie Burel
* <a href="mailto:j.burel@dundee.ac.uk">j.burel@dundee.ac.uk</a>
* @author Andrea Falconi
* <a href="mailto:a.falconi@dundee.ac.uk">a.falconi@dundee.ac.uk</a>
* @author Donald MacDonald
* <a href="mailto:donald@lifesci.dundee.ac.uk">donald@lifesci.dundee.ac.uk</a>
* @version 3.0
* <small>
* (<b>Internal version:</b> $Revision: $ $Date: $)
* </small>
* @since OME2.2
*/
class MoviePlayer
extends Player
{
/** Minimal value of the spinner. */
public static final int FPS_MIN = 1;
/** Initial value of the spinner. */
public static final int FPS_INIT = 12;
/** Indicates to play the movie in loops. */
protected static final int LOOP = 200;
/** Indicates to play the movie from end to start. */
protected static final int BACKWARD = 201;
/** Indicates to play the movie from start to end. */
protected static final int FORWARD = 202;
/** Indicates to play the movie round trip. */
protected static final int PINGPONG = 203;
/** Indicates to play the movie in loop starting from the end point. */
protected static final int LOOP_BACKWARD = 204;
/** The start z-section. */
private int startZ;
/** The end z-section. */
private int endZ;
/** The start timepoint. */
private int startT;
/** The end timepoint. */
private int endT;
/** The timer delay used for display. */
private int timerDelay;
/** The current z-section. */
private int frameNumberZ;
/** The current timepoint. */
private int frameNumberT;
/** The movie index. One of the following constants {@link #ACROSS_T},
* {@link #ACROSS_Z} or {@link #ACROSS_ZT}.
*/
private int index;
/**
* One of the following constants:
* {@link #LOOP}, {@link #BACKWARD}, {@link #FORWARD} or {@link #PINGPONG}.
*/
private int movieType;
/**
* Flag used to control the direction of play when the movie is played
* backward and forward.
*/
private boolean up;
/** Reference to the frame hosting this movie player. */
private MoviePlayerDialog parent;
/** The selected bin.*/
private int frameNumberBin;
/** The start bin. */
private int startBin;
/** The end bin. */
private int endBin;
/** Initializes the default values. */
private void initialize()
{
up = true;
movieType = FORWARD;
timerDelay = FPS_INIT;
startT = model.getRealSelectedT();
endT = getMaxT();
startZ = model.getDefaultZ();
endZ = getMaxZ();
startBin = model.getSelectedBin();
endBin = model.getMaxLifetimeBin();
if (timerDelay > getMaximumTimer()) timerDelay = getMaximumTimer();
setTimerDelay(timerDelay);
if (getMaxT() > 1) index = MoviePlayerDialog.ACROSS_T;
else if (getMaxZ() != 0) index = MoviePlayerDialog.ACROSS_Z;
else if (getMaxBin() > 1) index = MoviePlayerDialog.ACROSS_BIN;
}
/** Resets the frame number depending on the movie type. */
private void setFrameNumbers()
{
switch (movieType) {
case BACKWARD:
case LOOP_BACKWARD:
frameNumberZ = endZ;
frameNumberT = endT;
frameNumberBin = endBin;
break;
default:
frameNumberBin = startBin;
frameNumberZ = startZ;
frameNumberT = startT;
}
}
/** Plays movie across bins. */
private void playMovieAcrossBin()
{
switch (movieType) {
case LOOP:
if (frameNumberBin == endBin) frameNumberBin = startBin;
else frameNumberBin++;
break;
case LOOP_BACKWARD:
if (frameNumberBin == startZ) frameNumberBin = endBin;
else frameNumberBin--;
break;
case BACKWARD:
if (frameNumberBin == startBin) {
frameNumberBin = endBin;
setPlayerState(Player.STOP);
} else frameNumberBin--;
break;
case FORWARD:
if (frameNumberBin == endBin) {
frameNumberBin = startBin;
setPlayerState(Player.STOP);
} else frameNumberBin++;
break;
case PINGPONG:
if (frameNumberBin < endBin && up) frameNumberBin++;
else if (frameNumberBin > startBin && !up) frameNumberBin--;
else if (frameNumberBin == endBin && up) {
frameNumberBin--;
up = false;
} else if (frameNumberBin == startBin && !up) {
frameNumberBin++;
up = true;
}
}
}
/** Plays movie across z-sections. */
private void playMovieAcrossZ()
{
switch (movieType) {
case LOOP:
if (frameNumberZ == endZ) frameNumberZ = startZ;
else frameNumberZ++;
break;
case LOOP_BACKWARD:
if (frameNumberZ == startZ) frameNumberZ = endZ;
else frameNumberZ--;
break;
case BACKWARD:
if (frameNumberZ == startZ) {
frameNumberZ = endZ;
setPlayerState(Player.STOP);
} else frameNumberZ--;
break;
case FORWARD:
if (frameNumberZ == endZ) {
frameNumberZ = startZ;
setPlayerState(Player.STOP);
} else frameNumberZ++;
break;
case PINGPONG:
if (frameNumberZ < endZ && up) frameNumberZ++;
else if (frameNumberZ > startZ && !up) frameNumberZ--;
else if (frameNumberZ == endZ && up) {
frameNumberZ--;
up = false;
} else if (frameNumberZ == startZ && !up) {
frameNumberZ++;
up = true;
}
}
}
/** Plays movie across timepoints. */
private void playMovieAcrossT()
{
switch (movieType) {
case LOOP:
if (frameNumberT == endT) frameNumberT = startT;
else frameNumberT++;
break;
case LOOP_BACKWARD:
if (frameNumberT == startT) frameNumberT = endT;
else frameNumberT--;
break;
case BACKWARD:
if (frameNumberT == startT) {
frameNumberT = endT;
setPlayerState(Player.STOP);
} else frameNumberT--;
break;
case FORWARD:
if (frameNumberT == endT) {
frameNumberT = startT;
setPlayerState(Player.STOP);
} else frameNumberT++;
break;
case PINGPONG:
if (frameNumberT < endT && up) frameNumberT++;
else if (frameNumberT > startT && !up) frameNumberT--;
else if (frameNumberT == endT && up) {
frameNumberT--;
up = false;
} else if (frameNumberT == startT && !up) {
frameNumberT++;
up = true;
}
}
}
/** Plays movie across z-sections and timepoints. */
private void playMovieAcrossZT()
{
switch (movieType) {
case LOOP:
if (frameNumberZ == endZ) {
frameNumberZ = startZ;
if (frameNumberT == endT) {
frameNumberT = startT;
} else frameNumberT++;
} else frameNumberZ++;
break;
case LOOP_BACKWARD:
if (frameNumberZ == startZ) {
frameNumberZ = endZ;
if (frameNumberT == startT) {
frameNumberT = endT;
} else frameNumberT--;
} else frameNumberZ--;
break;
case BACKWARD:
if (frameNumberZ == startZ) {
frameNumberZ = endZ;
if (frameNumberT == startT) {
frameNumberT = endT;
setPlayerState(Player.STOP);
} else frameNumberT--;
} else frameNumberZ--;
break;
case FORWARD:
if (frameNumberZ == endZ) {
frameNumberZ = startZ;
if (frameNumberT == endT) {
frameNumberT = startT;
setPlayerState(Player.STOP);
} else frameNumberT++;
} else frameNumberZ++;
break;
case PINGPONG:
if (up) {
if (frameNumberZ == endZ) {
if (frameNumberT == endT) {
frameNumberZ--;
up = false;
} else {
frameNumberZ = startZ;
frameNumberT++;
}
} else frameNumberZ++;
} else {
if (frameNumberZ == startZ) {
if (frameNumberT == startT) {
frameNumberZ++;
up = true;
} else {
frameNumberZ = endZ;
frameNumberT--;
}
} else frameNumberZ--;
}
}
}
/**
* Creates a new instance.
*
* @param model Reference to the {@link ImViewer}.
* Mustn't be <code>null</code>.
* @param parent Reference to frame hosting this movie player.
* Mustn't be <code>null</code>.
*/
MoviePlayer(ImViewer model, MoviePlayerDialog parent)
{
super(model);
this.parent = parent;
initialize();
setFrameNumbers();
}
/**
* Returns the timer's delay.
*
* @return See above.
*/
int getTimerDelay() { return timerDelay; }
/**
* The maximum value of the timer.
*
* @return See above.
*/
int getMaximumTimer() { return Math.max(getMaxZ()+1, getMaxT()+1); }
/**
* Returns the type of movie currently played. One of the following
* constants: {@link #LOOP}, {@link #BACKWARD}, {@link #FORWARD} or
* {@link #PINGPONG}.
*
* @return See above.
*/
int getMovieType() { return movieType; }
/**
* Returns the maximum number of timepoints.
*
* @return See above.
*/
int getMaxT() { return model.getRealT()-1; }
/**
* Returns the maximum number of z-sections minus 1.
*
* @return See above.
*/
int getMaxZ() { return model.getMaxZ(); }
/**
* Returns the maximum number of bins.
*
* @return See above.
*/
int getMaxBin() { return model.getMaxLifetimeBin(); }
/**
* Returns the minimum value of bin.
*
* @return See above.
*/
int getMinBin() { return 0; }
/**
* Returns the minimum value of z-sections.
*
* @return See above.
*/
int getMinZ() { return 0; }
/**
* Returns the minimum value of timepoints.
*
* @return See above.
*/
int getMinT() { return 0; }
/**
* Sets the start timepoint.
*
* @param v The value to set.
*/
void setStartT(int v)
{
startT = v;
setPlayerState(Player.STOP);
setFrameNumbers();
}
/**
* Sets the start z-section.
*
* @param v The value to set.
*/
void setStartZ(int v)
{
startZ = v;
setPlayerState(Player.STOP);
setFrameNumbers();
}
/**
* Sets the start bin.
*
* @param v The value to set.
*/
void setStartBin(int v)
{
startBin = v;
setPlayerState(Player.STOP);
setFrameNumbers();
}
/**
* Sets the end timepoint.
*
* @param v The value to set.
*/
void setEndT(int v)
{
endT = v;
setPlayerState(Player.STOP);
setFrameNumbers();
}
/**
* Sets the end z-section.
*
* @param v The value to set.
*/
void setEndZ(int v)
{
endZ = v;
setPlayerState(Player.STOP);
setFrameNumbers();
}
/**
* Sets the end bin.
*
* @param v The value to set.
*/
void setEndBin(int v)
{
endBin = v;
setPlayerState(Player.STOP);
setFrameNumbers();
}
/**
* Sets the delay of the timer.
*
* @param delay
*/
void setTimerDelay(int delay)
{
setPlayerState(Player.STOP);
timerDelay = delay;
setDelay(delay);
}
/**
* Sets the type of movie to play.
*
* @param type The value to set.
*/
void setMovieType(int type)
{
setPlayerState(Player.STOP);
movieType = type;
}
/**
* Returns the starting timepoint.
*
* @return See above.
*/
int getStartT() { return startT; }
/**
* Returns the ending timepoint.
*
* @return See above.
*/
int getEndT() { return endT; }
/**
* Returns the starting z-section.
*
* @return See above.
*/
int getStartZ() { return startZ; }
/**
* Returns the ending z-section.
*
* @return See above.
*/
int getEndZ() { return endZ; }
/**
* Returns the movie index. One of the following constants:
* {@link #ACROSS_T}, {@link #ACROSS_Z} or {@link #ACROSS_ZT}.
*
* @return See above.
*/
int getMovieIndex() { return index; }
/**
* Sets the movie index. One of the following constants:
* {@link #ACROSS_T}, {@link #ACROSS_Z} or {@link #ACROSS_ZT}.
*
* @param index The value to set.
*/
void setMovieIndex(int index)
{
if (this.index == index) return;
setPlayerState(Player.STOP);
this.index = index;
}
/**
* Returns the current bin.
*
* @return See above.
*/
int getFrameNumberBin() { return frameNumberBin; }
/**
* Returns the current z-section.
*
* @return See above.
*/
int getFrameNumberZ() { return frameNumberZ; }
/**
* Returns the current timepoint.
*
* @return See above.
*/
int getFrameNumberT() { return frameNumberT; }
/**
* Overridden to play the movie.
* @see Player#onPlayerStateChange()
*/
protected void onPlayerStateChange()
{
switch (state) {
case START:
parent.setMoviePlay(true);
timer.start();
break;
case STOP:
parent.setMoviePlay(false);
timer.stop();
setFrameNumbers();
up = true;
break;
case PAUSE:
parent.setMoviePlay(false);
timer.stop();
}
}
/**
* Plays movie depending on the movie index.
* @see java.awt.event.ActionListener#actionPerformed(ActionEvent)
*/
public void actionPerformed(ActionEvent e)
{
switch (index) {
case MoviePlayerDialog.ACROSS_Z:
if (frameNumberZ <= getMaxZ() && frameNumberZ >= startZ
&& frameNumberZ <= endZ && state == Player.START) {
parent.renderImage();
playMovieAcrossZ();
}
break;
case MoviePlayerDialog.ACROSS_T:
if (frameNumberT <= getMaxT() && frameNumberT >= startT
&& frameNumberT <= endT && state == Player.START) {
parent.renderImage();
playMovieAcrossT();
}
break;
case MoviePlayerDialog.ACROSS_BIN:
if (frameNumberBin <= getMaxBin() && frameNumberBin >= startBin
&& frameNumberBin <= endBin && state == Player.START) {
parent.renderImage();
playMovieAcrossBin();
}
break;
case MoviePlayerDialog.ACROSS_ZT:
parent.renderImage();
playMovieAcrossZT();
break;
}
}
}