/*
* This file is part of libbluray
* Copyright (C) 2012 Libbluray
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
package java.awt;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask;
import org.videolan.Logger;
import org.videolan.Libbluray;
public class BDRootWindow extends Frame {
public BDRootWindow () {
super();
setUndecorated(true);
setBackground(new Color(0, 0, 0, 0));
BDToolkit.setFocusedWindow(this);
}
public Area getDirtyArea() {
return dirty;
}
public Font getDefaultFont() {
return defaultFont;
}
public void setDefaultFont(String fontId) {
if (fontId == null || fontId.equals("*****")) {
defaultFont = null;
} else {
try {
defaultFont = (new org.dvb.ui.FontFactory()).createFont(fontId);
} catch (Exception ex) {
logger.error("Failed setting default font " + fontId + ".otf: " + ex);
}
}
logger.info("setting default font to " + fontId + ".otf (" + defaultFont + ")");
setFont(defaultFont);
}
public void setBounds(int x, int y, int width, int height) {
if (!isVisible()) {
if ((width > 0) && (height > 0)) {
if ((backBuffer == null) || (getWidth() * getHeight() < width * height)) {
backBuffer = new int[width * height];
Arrays.fill(backBuffer, 0);
}
}
super.setBounds(x, y, width, height);
} else if (width != getWidth() || height != getHeight()){
logger.error("setBounds(" + x + "," + y + "," + width + "," + height + ") FAILED: already visible");
}
}
public int[] getBdBackBuffer() {
return backBuffer;
}
public Image getBackBuffer() {
/* exists only in J2SE */
logger.unimplemented("getBackBuffer");
return null;
}
private boolean isBackBufferClear() {
int v = 0;
for (int i = 0; i < height * width; i++)
v |= backBuffer[i];
return v == 0;
}
public void notifyChanged() {
if (!isVisible()) {
logger.error("sync(): not visible");
return;
}
synchronized (this) {
if (timer == null) {
logger.error("notifyChanged(): window already disposed");
return;
}
changeCount++;
if (timerTask == null) {
timerTask = new RefreshTimerTask(this);
timer.schedule(timerTask, 40, 40);
}
}
}
public void sync() {
synchronized (this) {
if (timerTask != null) {
timerTask.cancel();
timerTask = null;
}
changeCount = 0;
if (!isVisible()) {
if (overlay_open) {
logger.info("sync(): close OSD (not visible)");
close();
}
logger.info("sync() ignored (not visible)");
return;
}
Area a = dirty.getBoundsAndClear();
if (!a.isEmpty()) {
if (!overlay_open) {
/* delay opening overlay until something has been drawn */
if (isBackBufferClear()) {
logger.info("sync() ignored (overlay not open, empty overlay)");
return;
}
Libbluray.updateGraphic(getWidth(), getHeight(), null);
overlay_open = true;
a = new Area(getWidth(), getHeight()); /* force full plane update */
}
Libbluray.updateGraphic(getWidth(), getHeight(), backBuffer,
a.getX0(), a.getY0(), a.getX1(), a.getY1());
}
}
}
private static class RefreshTimerTask extends TimerTask {
public RefreshTimerTask(BDRootWindow window) {
this.window = window;
this.changeCount = window.changeCount;
}
public void run() {
synchronized (window) {
if (this.changeCount == window.changeCount)
window.sync();
else
this.changeCount = window.changeCount;
}
}
private BDRootWindow window;
private int changeCount;
}
private void close() {
synchronized (this) {
if (overlay_open) {
Libbluray.updateGraphic(0, 0, null);
overlay_open = false;
}
}
}
public void setVisible(boolean visible) {
super.setVisible(visible);
if (!visible) {
close();
}
}
/* called when new title starts (window is "created" again) */
public void clearOverlay() {
synchronized (this) {
if (overlay_open) {
logger.error("clearOverlay() ignored (overlay is visible)");
} else {
dirty.getBoundsAndClear();
Arrays.fill(backBuffer, 0);
}
}
}
public void dispose()
{
synchronized (this) {
if (timerTask != null) {
timerTask.cancel();
timerTask = null;
}
if (timer != null) {
timer.cancel();
timer = null;
}
}
if (isVisible()) {
hide();
}
BDToolkit.setFocusedWindow(null);
super.dispose();
backBuffer = null;
}
private int[] backBuffer = null;
private transient Area dirty = new Area();
private transient int changeCount = 0;
private transient Timer timer = new Timer();
private transient TimerTask timerTask = null;
private boolean overlay_open = false;
private Font defaultFont = null;
private static final Logger logger = Logger.getLogger(BDRootWindow.class.getName());
private static final long serialVersionUID = -8325961861529007953L;
}