/* * 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 * . */ 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; }