/*
This file is part of JFLICKS.
JFLICKS 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 3 of the License, or
(at your option) any later version.
JFLICKS 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 JFLICKS. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jflicks.ui.view.fe.screen;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import org.jflicks.nms.Media;
import org.jflicks.player.Bookmark;
import org.jflicks.player.Player;
import org.jflicks.player.PlayState;
import org.jflicks.rc.RC;
import org.jflicks.ui.view.fe.ButtonPanel;
import org.jflicks.ui.view.fe.FrontEndView;
import org.jflicks.util.LogUtil;
/**
* This abstract class supports playing a video in a front end UI on a TV,
* while keeping track of bookmarks.
*
* @author Doug Barnum
* @version 1.0
*/
public abstract class PlayerScreen extends Screen implements ActionListener {
/**
* A constant to define a "Play" menu item.
*/
public static final String PLAY = "Play";
/**
* A constant to define a "Play from Bookmark" menu item.
*/
public static final String PLAY_FROM_BOOKMARK = "Play from Bookmark";
/**
* A constant to define a "Play using ANY Tags" menu item.
*/
public static final String PLAY_USING_ANY_TAGS = "Play using ANY Tags";
/**
* A constant to define a "Play using ALL Tags" menu item.
*/
public static final String PLAY_USING_ALL_TAGS = "Play using ALL Tags";
/**
* A constant to define a "Stop Recording" menu item.
*/
public static final String STOP_RECORDING = "Stop Recording";
/**
* A constant to define a "Delete" menu item.
*/
public static final String DELETE = "Delete";
/**
* A constant to define a "Delete (Allow Re-Recording)" menu item.
*/
public static final String DELETE_ALLOW_RERECORDING =
"Delete (Allow Re-Recording)";
/**
* A constant to define a "Cancel" menu item.
*/
public static final String CANCEL = "Cancel";
private HashMap<String, Bookmark> bookmarkHashMap;
private File bookmarkFile;
private ButtonPanel playButtonPanel;
private JPanel blankPanel;
private boolean popupEnabled;
private long markTime;
/**
* Extensions need to display some info banner over the video.
*/
public abstract void info();
/**
* Extensions might need to display some guide information or control.
*/
public abstract void guide();
/**
* Extensions might need to do something with a page up.
*/
public abstract void pageup();
/**
* Extensions might need to do something with a page down.
*/
public abstract void pagedown();
/**
* If anything needs to be "cleaned up" after the stopping of video,
* extensions should do it here.
*/
public abstract void close();
/**
* Extensions should perform a rewind.
*/
public abstract void rewind();
/**
* Extensions should perform a forward.
*/
public abstract void forward();
/**
* Extensions should perform a skip forward.
*/
public abstract void skipforward();
/**
* Extensions should perform a skip backward.
*/
public abstract void skipbackward();
/**
* Extensions can do what they want with an up command.
*/
public abstract void up();
/**
* Extensions can do what they want with a down command.
*/
public abstract void down();
/**
* Extensions can do what they want with a left command.
*/
public abstract void left();
/**
* Extensions can do what they want with a right command.
*/
public abstract void right();
/**
* Extensions can do what they want with an enter command.
*/
public abstract void enter();
/**
* Create a Bookmark instance.
*
* @return A Bookmark instance.
*/
public abstract Bookmark createBookmark();
/**
* What ID should be used for the current bookmark.
*
* @return An Id as a String.
*/
public abstract String getBookmarkId();
/**
* Simple empty constructor.
*/
public PlayerScreen() {
setBookmarkHashMap(new HashMap<String, Bookmark>());
}
protected File getBookmarkFile() {
return (bookmarkFile);
}
protected void setBookmarkFile(File f) {
bookmarkFile = f;
}
private HashMap<String, Bookmark> getBookmarkHashMap() {
return (bookmarkHashMap);
}
private void setBookmarkHashMap(HashMap<String, Bookmark> m) {
bookmarkHashMap = m;
}
protected void putBookmark(String id, Bookmark b) {
HashMap<String, Bookmark> m = getBookmarkHashMap();
if ((m != null) && (id != null) && (b != null)) {
m.put(id, b);
}
}
protected void deleteBookmark(String id) {
HashMap<String, Bookmark> m = getBookmarkHashMap();
if ((m != null) && (id != null)) {
m.remove(id);
}
}
protected Bookmark getBookmark(String id) {
Bookmark result = null;
HashMap<String, Bookmark> m = getBookmarkHashMap();
if ((m != null) && (id != null)) {
result = m.get(id);
}
return (result);
}
protected void saveBookmark(Player p) {
Bookmark b = createBookmark();
if (b != null) {
String id = getBookmarkId();
if (id != null) {
putBookmark(id, b);
}
}
}
protected boolean hasBookmark(String id) {
return (getBookmark(id) != null);
}
/**
* A panel that will be drawn over the current UI to "blank" it out.
*
* @return A JPanel instance.
*/
public JPanel getBlankPanel() {
return (blankPanel);
}
/**
* A panel that will be drawn over the current UI to "blank" it out.
*
* @param p A JPanel instance.
*/
public void setBlankPanel(JPanel p) {
blankPanel = p;
}
/**
* When launching a Player it is handy to "blank out" the UI in case the
* player does not fully cover the screen. This will use the BlankPanel
* property if it exists.
*/
public void addBlankPanel() {
JPanel p = getBlankPanel();
JLayeredPane pane = getLayeredPane();
if ((p != null) && (pane != null)) {
pane.add(p, Integer.valueOf(190));
pane.repaint();
}
}
/**
* When launching a Player it is handy to "blank out" the UI in case the
* player does not fully cover the screen. This will use the BlankPanel
* property if it exists.
*/
public void removeBlankPanel() {
LogUtil.log(LogUtil.DEBUG, "removeBlankPanel now");
JPanel p = getBlankPanel();
JLayeredPane pane = getLayeredPane();
if ((p != null) && (pane != null)) {
pane.remove(p);
pane.repaint();
}
}
@SuppressWarnings("unchecked")
protected void load() {
try {
HashMap<String, Bookmark> m = null;
File file = getBookmarkFile();
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(file));
Object obj = ois.readObject();
if (obj instanceof HashMap<?, ?>) {
m = (HashMap<String, Bookmark>) obj;
}
ois.close();
if (m != null) {
setBookmarkHashMap(m);
}
} catch (ClassNotFoundException ex) {
LogUtil.log(LogUtil.WARNING, "Error loading bookmarks:" + ex.getMessage());
} catch (IOException ex) {
LogUtil.log(LogUtil.WARNING, "Error loading bookmarks:" + ex.getMessage());
}
}
/**
* {@inheritDoc}
*/
public void save() {
HashMap<String, Bookmark> l = getBookmarkHashMap();
if (l != null) {
try {
File file = getBookmarkFile();
if (file != null) {
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(file));
oos.writeObject(l);
oos.close();
}
} catch (IOException ex) {
LogUtil.log(LogUtil.WARNING, "Error saving bookmarks:" + ex.getMessage());
}
}
}
protected ButtonPanel getPlayButtonPanel() {
return (playButtonPanel);
}
private void setPlayButtonPanel(ButtonPanel p) {
playButtonPanel = p;
}
protected boolean isPopupEnabled() {
return (popupEnabled);
}
protected void setPopupEnabled(boolean b) {
popupEnabled = b;
}
protected void popup(String[] choices) {
JLayeredPane pane = getLayeredPane();
if ((pane != null) && (choices != null)) {
Dimension d = pane.getSize();
int width = (int) d.getWidth();
int height = (int) d.getHeight();
// See if we have an image as a backgraound...
BufferedImage bi = null;
FrontEndView fe = (FrontEndView) getView();
if (fe != null) {
bi = fe.getLogoImage();
}
ButtonPanel bp = new ButtonPanel();
bp.addActionListener(this);
bp.setButtons(choices);
bp.setBufferedImage(bi);
setPlayButtonPanel(bp);
d = bp.getPreferredSize();
int bpwidth = (int) d.getWidth();
int bpheight = (int) d.getHeight();
int bpx = (int) ((width - bpwidth) / 2);
int bpy = (int) ((height - bpheight) / 2);
bp.setBounds(bpx, bpy, bpwidth, bpheight);
setPopupEnabled(true);
pane.add(bp, Integer.valueOf(300));
bp.setControl(true);
bp.setButtons(choices);
bp.requestFocus();
}
}
protected void unpopup() {
setPopupEnabled(false);
JLayeredPane pane = getLayeredPane();
ButtonPanel bp = getPlayButtonPanel();
if ((pane != null) && (bp != null)) {
bp.removeActionListener(this);
setPlayButtonPanel(null);
pane.remove(bp);
pane.repaint();
}
}
public long getMarkTime() {
return (markTime);
}
public void setMarkTime(long l) {
markTime = l;
}
public int leftToGo(Player p, long startedAt) {
int result = -1;
if (p != null) {
PlayState ps = p.getPlayState();
if (ps != null) {
double current = ps.getTime();
double len = (double) (System.currentTimeMillis() - startedAt);
len /= 1000.0;
result = (int) (len - current);
}
}
return (result);
}
public int leftToGo(Player p, Media m) {
int result = -1;
if (p != null) {
PlayState ps = p.getPlayState();
if (ps != null) {
double current = ps.getTime();
double len = m.getDuration();
result = (int) (len - current);
}
}
return (result);
}
/**
* Screens that use a Player sometimes need to turn keyboard control
* on or off - this is simulated keystrokes via our RC instance.
*
* @param b True if keyboard control is needed.
*/
public void controlKeyboard(boolean b) {
RC remote = getRC();
if (remote != null) {
remote.setKeyboardControl(b);
}
}
/**
* {@inheritDoc}
*/
public void commandReceived(String s) {
Player p = getPlayer();
if ((s != null) && (p != null) && (!isDone())) {
if (p.isPlaying()) {
// Then we pay attention to remote events...
LogUtil.log(LogUtil.DEBUG, getClass().getName() + " commandReceived: " + s);
if (s.equals(RC.ESCAPE_COMMAND)) {
LogUtil.log(LogUtil.DEBUG, "OK we are to close up shop!");
setBlocking(false);
saveBookmark(p);
p.stop();
close();
requestFocus();
} else if (s.equals(RC.PAUSE_COMMAND)) {
p.pause(!p.isPaused());
} else if (s.equals(RC.INFO_COMMAND)) {
info();
} else if (s.equals(RC.PAGE_UP_COMMAND)) {
pageup();
} else if (s.equals(RC.PAGE_DOWN_COMMAND)) {
pagedown();
} else if (s.equals(RC.GUIDE_COMMAND)) {
guide();
} else if (s.equals(RC.REWIND_COMMAND)) {
rewind();
} else if (s.equals(RC.FORWARD_COMMAND)) {
forward();
} else if (s.equals(RC.LEFT_COMMAND)) {
left();
} else if (s.equals(RC.RIGHT_COMMAND)) {
right();
} else if (s.equals(RC.SKIPBACKWARD_COMMAND)) {
skipbackward();
} else if (s.equals(RC.SKIPFORWARD_COMMAND)) {
skipforward();
} else if (s.equals(RC.UP_COMMAND)) {
up();
} else if (s.equals(RC.DOWN_COMMAND)) {
down();
} else if (s.equals(RC.ENTER_COMMAND)) {
enter();
} else if (s.equals(RC.SAP_COMMAND)) {
p.sap();
} else if (s.equals(RC.AUDIOSYNC_PLUS_COMMAND)) {
p.audiosync(0.1);
} else if (s.equals(RC.AUDIOSYNC_MINUS_COMMAND)) {
p.audiosync(-0.1);
}
}
}
}
}